Revert "Merge branch 'main' of https://gitlab.com/jeseibel/distant-horizons-core into serverside"
This reverts commita15aaa573d, reversing changes made to83c1a2fd63.
This commit is contained in:
@@ -23,9 +23,7 @@ import com.seibel.distanthorizons.api.interfaces.events.IDhApiEventInjector;
|
||||
import com.seibel.distanthorizons.api.interfaces.factories.IDhApiWrapperFactory;
|
||||
import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable;
|
||||
import com.seibel.distanthorizons.api.interfaces.override.worldGenerator.IDhApiWorldGeneratorOverrideRegister;
|
||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderObjectFactory;
|
||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderProxy;
|
||||
import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiAfterDhInitEvent;
|
||||
import com.seibel.distanthorizons.api.methods.override.DhApiWorldGeneratorOverrideRegister;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
@@ -129,12 +127,6 @@ public class DhApi
|
||||
*/
|
||||
public static IDhApiWrapperFactory wrapperFactory = null;
|
||||
|
||||
/**
|
||||
* Used to create custom renderable objects. <br>
|
||||
* These objects can be added to the renderer in {@link IDhApiLevelWrapper}
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
public static IDhApiCustomRenderObjectFactory customRenderObjectFactory = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
-67
@@ -1,67 +0,0 @@
|
||||
package com.seibel.distanthorizons.api.enums.rendering;
|
||||
|
||||
/**
|
||||
* contains the indices used by shaders to determine
|
||||
* how different block types should be rendered. <br><br>
|
||||
*
|
||||
* UNKNOWN, <br>
|
||||
* LEAVES, <br>
|
||||
* STONE, <br>
|
||||
* WOOD, <br>
|
||||
* METAL, <br>
|
||||
* DIRT, <br>
|
||||
* LAVA, <br>
|
||||
* DEEPSLATE, <br>
|
||||
* SNOW, <br>
|
||||
* SAND, <br>
|
||||
* TERRACOTTA, <br>
|
||||
* NETHER_STONE, <br>
|
||||
* WATER, <br>
|
||||
* GRASS, <br>
|
||||
* AIR, <br>
|
||||
* ILLUMINATED, <br>
|
||||
*
|
||||
* @author James Seibel
|
||||
* @since API 3.0.0
|
||||
* @version 2024-7-11
|
||||
*/
|
||||
public enum EDhApiBlockMaterial
|
||||
{
|
||||
UNKNOWN(0),
|
||||
LEAVES(1),
|
||||
STONE(2),
|
||||
WOOD(3),
|
||||
METAL(4),
|
||||
DIRT(5),
|
||||
LAVA(6),
|
||||
DEEPSLATE(7),
|
||||
SNOW(8),
|
||||
SAND(9),
|
||||
TERRACOTTA(10),
|
||||
NETHER_STONE(11),
|
||||
WATER(12),
|
||||
GRASS(13),
|
||||
/** shouldn't normally be needed, but just in case */
|
||||
AIR(14),
|
||||
ILLUMINATED(15); // Max value
|
||||
|
||||
|
||||
|
||||
public final byte index;
|
||||
|
||||
EDhApiBlockMaterial(int index) { this.index = (byte)index;}
|
||||
|
||||
public static EDhApiBlockMaterial getFromIndex(int index)
|
||||
{
|
||||
for(EDhApiBlockMaterial material : EDhApiBlockMaterial.values())
|
||||
{
|
||||
if (material.index == index)
|
||||
{
|
||||
return material;
|
||||
}
|
||||
}
|
||||
|
||||
return EDhApiBlockMaterial.UNKNOWN;
|
||||
}
|
||||
|
||||
}
|
||||
+3
-12
@@ -30,21 +30,12 @@ import com.seibel.distanthorizons.api.interfaces.IDhApiUnsafeWrapper;
|
||||
*/
|
||||
public interface IDhApiBlockStateWrapper extends IDhApiUnsafeWrapper
|
||||
{
|
||||
/** @since API 1.0.0 */
|
||||
boolean isAir();
|
||||
|
||||
/** @since API 1.0.0 */
|
||||
boolean isSolid();
|
||||
/** @since API 1.0.0 */
|
||||
boolean isLiquid();
|
||||
|
||||
/**
|
||||
* Returns the full serialized form of the given block
|
||||
* as defined by DH's serialization methods.
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
String getSerialString();
|
||||
/** @since API 3.0.0 */
|
||||
byte getMaterialId();
|
||||
|
||||
// TODO:
|
||||
// boolean hasNoCollision();
|
||||
// boolean noFaceIsFullFace();
|
||||
}
|
||||
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2023 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.api.interfaces.config.client;
|
||||
|
||||
import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigGroup;
|
||||
import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue;
|
||||
|
||||
/**
|
||||
* Distant Horizons' generic rendering configuration. <br><br>
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 2024-7-11
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
public interface IDhApiGenericRenderingConfig extends IDhApiConfigGroup
|
||||
{
|
||||
/**
|
||||
* If enabled DH will render generic objects into its terrain pass. <br>
|
||||
* This includes: clouds, beacons, and API added objects.
|
||||
*/
|
||||
IDhApiConfigValue<Boolean> renderingEnabled();
|
||||
|
||||
/** If enabled DH will render beacon beams. */
|
||||
IDhApiConfigValue<Boolean> beaconRenderingEnabled();
|
||||
|
||||
/** If enabled DH will render clouds. */
|
||||
IDhApiConfigValue<Boolean> cloudRenderingEnabled();
|
||||
|
||||
}
|
||||
-1
@@ -41,7 +41,6 @@ public interface IDhApiGraphicsConfig extends IDhApiConfigGroup
|
||||
IDhApiFogConfig fog();
|
||||
IDhApiAmbientOcclusionConfig ambientOcclusion();
|
||||
IDhApiNoiseTextureConfig noiseTexture();
|
||||
IDhApiGenericRenderingConfig genericRendering();
|
||||
|
||||
|
||||
|
||||
|
||||
-21
@@ -1,21 +0,0 @@
|
||||
package com.seibel.distanthorizons.api.interfaces.data;
|
||||
|
||||
/**
|
||||
* Can be used to drastically speed up repeat read operations in {@link IDhApiTerrainDataRepo}.
|
||||
*
|
||||
* @see IDhApiTerrainDataRepo
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 2024-7-14
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
public interface IDhApiTerrainDataCache
|
||||
{
|
||||
/**
|
||||
* Removes any data that's currently stored in this cache.
|
||||
* This cane be done to free up memory or invalidate
|
||||
* the cache so fresh data can be pulled in.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
}
|
||||
+12
-69
@@ -29,8 +29,6 @@ import com.seibel.distanthorizons.api.objects.data.DhApiTerrainDataPoint;
|
||||
/**
|
||||
* Used to interface with Distant Horizons' terrain data.
|
||||
*
|
||||
* @see IDhApiTerrainDataCache
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 2023-6-22
|
||||
* @since API 1.0.0
|
||||
@@ -42,50 +40,29 @@ public interface IDhApiTerrainDataRepo
|
||||
// getters //
|
||||
//=========//
|
||||
|
||||
/** @see IDhApiTerrainDataRepo#getSingleDataPointAtBlockPos(IDhApiLevelWrapper, int, int, int, IDhApiTerrainDataCache) */
|
||||
default DhApiResult<DhApiTerrainDataPoint> getSingleDataPointAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosY, int blockPosZ) { return this.getSingleDataPointAtBlockPos(levelWrapper, blockPosX, blockPosY, blockPosZ, null); }
|
||||
/**
|
||||
* Returns the terrain datapoint at the given block position, at/or containing the given Y position.
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
DhApiResult<DhApiTerrainDataPoint> getSingleDataPointAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosY, int blockPosZ, IDhApiTerrainDataCache dataCache);
|
||||
/** Returns the terrain datapoint at the given block position, at/or containing the given Y position. */
|
||||
DhApiResult<DhApiTerrainDataPoint> getSingleDataPointAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosY, int blockPosZ);
|
||||
/** Returns every datapoint in the column located at the given block X and Z position top to bottom. */
|
||||
DhApiResult<DhApiTerrainDataPoint[]> getColumnDataAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosZ);
|
||||
|
||||
/** @see IDhApiTerrainDataRepo#getColumnDataAtBlockPos(IDhApiLevelWrapper, int, int, IDhApiTerrainDataCache) */
|
||||
default DhApiResult<DhApiTerrainDataPoint[]> getColumnDataAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosZ) { return this.getColumnDataAtBlockPos(levelWrapper, blockPosX, blockPosZ, null); }
|
||||
/**
|
||||
* Returns every datapoint in the column located at the given block X and Z position top to bottom.
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
DhApiResult<DhApiTerrainDataPoint[]> getColumnDataAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosZ, IDhApiTerrainDataCache dataCache);
|
||||
|
||||
/** @see IDhApiTerrainDataRepo#getAllTerrainDataAtChunkPos(IDhApiLevelWrapper, int, int, IDhApiTerrainDataCache) */
|
||||
default DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtChunkPos(IDhApiLevelWrapper levelWrapper, int chunkPosX, int chunkPosZ) { return this.getAllTerrainDataAtChunkPos(levelWrapper, chunkPosX, chunkPosZ, null); }
|
||||
/**
|
||||
* Returns every datapoint in the given chunk's X and Z position. <br><br>
|
||||
*
|
||||
* The returned array is ordered: [relativeBlockX][relativeBlockZ][columnIndex] <br>
|
||||
* RelativeBlockX/Z are relative to the block position closest to negative infinity in the chunk's position. <br>
|
||||
* The column data is ordered from top to bottom. Note: each column may have a different number of values. <br>
|
||||
*
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtChunkPos(IDhApiLevelWrapper levelWrapper, int chunkPosX, int chunkPosZ, IDhApiTerrainDataCache dataCache);
|
||||
DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtChunkPos(IDhApiLevelWrapper levelWrapper, int chunkPosX, int chunkPosZ);
|
||||
|
||||
/** @see IDhApiTerrainDataRepo#getAllTerrainDataAtRegionPos(IDhApiLevelWrapper, int, int, IDhApiTerrainDataCache) */
|
||||
default DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtRegionPos(IDhApiLevelWrapper levelWrapper, int regionPosX, int regionPosZ) { return this.getAllTerrainDataAtRegionPos(levelWrapper, regionPosX, regionPosZ, null); }
|
||||
/**
|
||||
* Returns every datapoint in the given region's X and Z position. <br><br>
|
||||
*
|
||||
* The returned array is ordered: [relativeBlockX][relativeBlockZ][columnIndex] <br>
|
||||
* RelativeBlockX/Z are relative to the block position closest to negative infinity in the region's position. <br>
|
||||
* The column data is ordered from top to bottom. Note: each column may have a different number of values. <br>
|
||||
*
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtRegionPos(IDhApiLevelWrapper levelWrapper, int regionPosX, int regionPosZ, IDhApiTerrainDataCache dataCache);
|
||||
DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtRegionPos(IDhApiLevelWrapper levelWrapper, int regionPosX, int regionPosZ);
|
||||
|
||||
/** @see IDhApiTerrainDataRepo#getAllTerrainDataAtDetailLevelAndPos(IDhApiLevelWrapper, byte, int, int, IDhApiTerrainDataCache) */
|
||||
default DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtRegionPos(IDhApiLevelWrapper levelWrapper, byte detailLevel, int posX, int posZ) { return this.getAllTerrainDataAtDetailLevelAndPos(levelWrapper, detailLevel, posX, posZ, null); }
|
||||
/**
|
||||
* Returns every datapoint in the column located at the given detail level and X/Z position. <br>
|
||||
* This can be used to return terrain data for non-standard sizes (IE 2x2 blocks or 2x2 chunks).
|
||||
@@ -94,42 +71,20 @@ public interface IDhApiTerrainDataRepo
|
||||
* Every increase doubles the width of the returned area. <br>
|
||||
* Example values: 0 = block, 1 = 2x2 blocks, 2 = 4x4 blocks, ... 4 = chunk (16x16 blocks), ... 9 = region (512x512 blocks) <br>
|
||||
* See {@link EDhApiDetailLevel} for more information.
|
||||
*
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtDetailLevelAndPos(IDhApiLevelWrapper levelWrapper, byte detailLevel, int posX, int posZ, IDhApiTerrainDataCache dataCache);
|
||||
|
||||
|
||||
|
||||
/** @see IDhApiTerrainDataRepo#raycast(IDhApiLevelWrapper, double, double, double, float, float, float, int, IDhApiTerrainDataCache) */
|
||||
default DhApiResult<DhApiRaycastResult> raycast(
|
||||
IDhApiLevelWrapper levelWrapper,
|
||||
double rayOriginX, double rayOriginY, double rayOriginZ,
|
||||
float rayDirectionX, float rayDirectionY, float rayDirectionZ,
|
||||
int maxRayBlockLength)
|
||||
{
|
||||
return this.raycast(
|
||||
levelWrapper,
|
||||
rayOriginX, rayOriginY, rayOriginZ,
|
||||
rayDirectionX, rayDirectionY, rayDirectionZ,
|
||||
maxRayBlockLength,
|
||||
null);
|
||||
}
|
||||
DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtDetailLevelAndPos(IDhApiLevelWrapper levelWrapper, byte detailLevel, int posX, int posZ);
|
||||
|
||||
/**
|
||||
* Returns the datapoint and position of the LOD
|
||||
* at the end of the given ray. <br><br>
|
||||
*
|
||||
* Will return "success" with a null datapoint if the ray reaches the max length without finding any data.
|
||||
*
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
DhApiResult<DhApiRaycastResult> raycast(
|
||||
IDhApiLevelWrapper levelWrapper,
|
||||
double rayOriginX, double rayOriginY, double rayOriginZ,
|
||||
float rayDirectionX, float rayDirectionY, float rayDirectionZ,
|
||||
int maxRayBlockLength,
|
||||
IDhApiTerrainDataCache dataCache);
|
||||
int maxRayBlockLength);
|
||||
|
||||
|
||||
|
||||
@@ -143,27 +98,15 @@ public interface IDhApiTerrainDataRepo
|
||||
* Notes: <br>
|
||||
* - Only works if the given {@link IDhApiLevelWrapper} points to a loaded level. <br>
|
||||
* - If the player travels to this chunk, or the chunk is updated in some other way; your data will be replaced
|
||||
* by whatever the current chunk is. <br>
|
||||
* - This method may not update the LOD data immediately. Any other chunks that have
|
||||
* been queued to update will be handled first.
|
||||
* by whatever the current chunk is. <br>
|
||||
* - This method may not update the LOD data immediately. Any other chunks have
|
||||
* been queued to update, they will be handled first.
|
||||
*
|
||||
* @param levelWrapper the level wrapper that the chunk should be saved to.
|
||||
* @param chunkObjectArray see {@link IDhApiWorldGenerator#generateChunks} for what objects are expected.
|
||||
* @throws ClassCastException if chunkObjectArray doesn't contain the right objects.
|
||||
* The exception will contain the expected object(s).
|
||||
*/
|
||||
DhApiResult<Void> overwriteChunkDataAsync(IDhApiLevelWrapper levelWrapper, Object[] chunkObjectArray) throws ClassCastException;
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// helpers //
|
||||
//=========//
|
||||
|
||||
/**
|
||||
* @return a {@link IDhApiTerrainDataCache} backed by {@link java.lang.ref.SoftReference}'s.
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
IDhApiTerrainDataCache getSoftCache();
|
||||
public DhApiResult<Void> overwriteChunkDataAsync(IDhApiLevelWrapper levelWrapper, Object[] chunkObjectArray) throws ClassCastException;
|
||||
|
||||
}
|
||||
|
||||
+6
-29
@@ -79,34 +79,11 @@ public interface IDhApiWrapperFactory
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a {@link IDhApiBiomeWrapper} for use by other DhApi methods.
|
||||
*
|
||||
* @param resourceLocationString example: "minecraft:plains"
|
||||
*
|
||||
* @param levelWrapper Expects a {@link IDhApiLevelWrapper} returned by one of DH's {@link DhApi.Delayed#worldProxy} methods. <br>
|
||||
* A custom implementation of {@link IDhApiLevelWrapper} will not be accepted.
|
||||
*
|
||||
* @throws IOException if the resourceLocationString wasn't able to be parsed or converted into a valid {@link IDhApiBiomeWrapper}
|
||||
* @throws ClassCastException if the wrong levelWrapper type was given
|
||||
*
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
IDhApiBiomeWrapper getBiomeWrapper(String resourceLocationString, IDhApiLevelWrapper levelWrapper) throws IOException, ClassCastException;
|
||||
|
||||
/**
|
||||
* Constructs a {@link IDhApiBlockStateWrapper} for use by other DhApi methods.
|
||||
* This returns the default blockstate for the given resource location.
|
||||
*
|
||||
* @param resourceLocationString examples: "minecraft:bedrock", "minecraft:stone", "minecraft:grass_block"
|
||||
* @param levelWrapper Expects a {@link IDhApiBlockStateWrapper} returned by one of DH's {@link DhApi.Delayed#worldProxy} methods. <br>
|
||||
* A custom implementation of {@link IDhApiBlockStateWrapper} will not be accepted.
|
||||
*
|
||||
* @throws IOException if the resourceLocationString wasn't able to be parsed or converted into a valid {@link IDhApiBlockStateWrapper}
|
||||
* @throws ClassCastException if the wrong levelWrapper type was given
|
||||
*
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
IDhApiBlockStateWrapper getDefaultBlockStateWrapper(String resourceLocationString, IDhApiLevelWrapper levelWrapper) throws IOException, ClassCastException;
|
||||
///**
|
||||
// * Specifically designed to be used with the API.
|
||||
// *
|
||||
// * @throws ClassCastException with instructions on expected objects if the object couldn't be cast
|
||||
// */
|
||||
//IChunkWrapper createChunkWrapper(Object[] objectArray) throws ClassCastException;
|
||||
|
||||
}
|
||||
|
||||
+2
-2
@@ -21,7 +21,7 @@ package com.seibel.distanthorizons.api.interfaces.override.rendering;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.EDhApiDetailLevel;
|
||||
import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
|
||||
|
||||
/**
|
||||
* Used to determine if a LOD should be rendered or is outside the
|
||||
@@ -41,7 +41,7 @@ public interface IDhApiCullingFrustum extends IDhApiOverrideable
|
||||
* @param worldMaxBlockY the highest block position this level allows.
|
||||
* @param worldViewProjection the projection matrix used in this render pass.
|
||||
*/
|
||||
void update(int worldMinBlockY, int worldMaxBlockY, DhApiMat4f worldViewProjection);
|
||||
void update(int worldMinBlockY, int worldMaxBlockY, Mat4f worldViewProjection);
|
||||
|
||||
/**
|
||||
* returns true if the LOD bounds intersect this frustum
|
||||
|
||||
-80
@@ -1,80 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2023 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.api.interfaces.override.rendering;
|
||||
|
||||
import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable;
|
||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
|
||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
|
||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading;
|
||||
|
||||
/**
|
||||
* @see IDhApiShaderProgram
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 2024-7-11
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
public interface IDhApiGenericObjectShaderProgram extends IDhApiOverrideable
|
||||
{
|
||||
|
||||
/**
|
||||
* If this method is called that means this program has the highest priority as defined by {@link IDhApiOverrideable#getPriority()}
|
||||
* and gets to decide if it wants to be used to render this frame or not. <br><br>
|
||||
*
|
||||
* If this method returns true then this program will be used for this frame. <br>
|
||||
* If this returns false then the default DH {@link IDhApiGenericObjectShaderProgram} will be used instead.
|
||||
*/
|
||||
boolean overrideThisFrame();
|
||||
|
||||
/** @return the OpenGL ID for this shader program */
|
||||
int getId();
|
||||
|
||||
/** Free any OpenGL objects owned by this program. */
|
||||
void free();
|
||||
|
||||
/** Runs any necessary binding this program needs so rendering can be done. */
|
||||
void bind(DhApiRenderParam renderEventParam);
|
||||
/** Runs any necessary unbinding this program needs so rendering can be done by another program. */
|
||||
void unbind();
|
||||
|
||||
/** Binds the given Vertex Buffer Object to this shader program for rendering. */
|
||||
void bindVertexBuffer(int vbo);
|
||||
|
||||
|
||||
/** sets up the necessary uniforms for rendering */
|
||||
void fillIndirectUniformData(
|
||||
DhApiRenderParam renderParameters,
|
||||
DhApiRenderableBoxGroupShading shading, IDhApiRenderableBoxGroup boxGroup,
|
||||
DhApiVec3d camPos);
|
||||
|
||||
/** sets up the necessary uniforms for rendering */
|
||||
void fillSharedDirectUniformData(
|
||||
DhApiRenderParam renderParameters,
|
||||
DhApiRenderableBoxGroupShading shading, IDhApiRenderableBoxGroup boxGroup,
|
||||
DhApiVec3d camPos);
|
||||
void fillDirectUniformData(
|
||||
DhApiRenderParam renderParameters,
|
||||
IDhApiRenderableBoxGroup boxGroup, DhApiRenderableBox box,
|
||||
DhApiVec3d camPos);
|
||||
|
||||
|
||||
}
|
||||
+3
-4
@@ -21,11 +21,10 @@ package com.seibel.distanthorizons.api.interfaces.override.rendering;
|
||||
|
||||
import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Vec3f;
|
||||
|
||||
/**
|
||||
* @see IDhApiGenericObjectShaderProgram
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 2024-1-24
|
||||
* @since API 2.0.0
|
||||
@@ -58,7 +57,7 @@ public interface IDhApiShaderProgram extends IDhApiOverrideable
|
||||
void fillUniformData(DhApiRenderParam renderParameters);
|
||||
|
||||
/** sets the vec3 that all DH verticies should be offset by when rendering */
|
||||
void setModelOffsetPos(DhApiVec3f modelPos);
|
||||
void setModelOffsetPos(Vec3f modelPos);
|
||||
|
||||
/** Binds the given Vertex Buffer Object to this shader program for rendering. */
|
||||
void bindVertexBuffer(int vbo);
|
||||
|
||||
+4
@@ -19,6 +19,10 @@
|
||||
|
||||
package com.seibel.distanthorizons.api.interfaces.override.rendering;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.EDhApiDetailLevel;
|
||||
import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
|
||||
|
||||
/**
|
||||
* The culling frustum used during Distant Horizons' shadow pass
|
||||
* if another mod has enabled Distant Horizons' shadow
|
||||
|
||||
+1
-48
@@ -22,8 +22,6 @@ package com.seibel.distanthorizons.api.interfaces.override.worldGenerator;
|
||||
import com.seibel.distanthorizons.api.enums.EDhApiDetailLevel;
|
||||
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode;
|
||||
import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable;
|
||||
import com.seibel.distanthorizons.api.objects.data.DhApiChunk;
|
||||
import com.seibel.distanthorizons.api.objects.data.DhApiTerrainDataPoint;
|
||||
import com.seibel.distanthorizons.coreapi.util.BitShiftUtil;
|
||||
|
||||
import java.io.Closeable;
|
||||
@@ -79,41 +77,13 @@ public abstract class AbstractDhApiChunkWorldGenerator implements Closeable, IDh
|
||||
}, worldGeneratorThreadPool);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final CompletableFuture<Void> generateApiChunks(
|
||||
int chunkPosMinX,
|
||||
int chunkPosMinZ,
|
||||
byte granularity,
|
||||
byte targetDataDetail,
|
||||
EDhApiDistantGeneratorMode generatorMode,
|
||||
ExecutorService worldGeneratorThreadPool,
|
||||
Consumer<DhApiChunk> resultConsumer
|
||||
)
|
||||
{
|
||||
return CompletableFuture.runAsync(() ->
|
||||
{
|
||||
// TODO what does this mean?
|
||||
int genChunkWidth = BitShiftUtil.powerOfTwo(granularity - 4);
|
||||
|
||||
for (int chunkX = chunkPosMinX; chunkX < chunkPosMinX + genChunkWidth; chunkX++)
|
||||
{
|
||||
for (int chunkZ = chunkPosMinZ; chunkZ < chunkPosMinZ + genChunkWidth; chunkZ++)
|
||||
{
|
||||
DhApiChunk apiChunk = this.generateApiChunk(chunkX, chunkZ, generatorMode);
|
||||
resultConsumer.accept(apiChunk);
|
||||
}
|
||||
}
|
||||
}, worldGeneratorThreadPool);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This method is called to generate terrain over a given area
|
||||
* from a thread defined by Distant Horizons. <br><br>
|
||||
*
|
||||
* @param chunkPosX the chunk X position in the level (not to be confused with the chunk's BlockPos in the level)
|
||||
* @param chunkPosZ the chunk Z position in the level (not to be confused with the chunk's BlockPos in the level)
|
||||
* @param generatorMode how far into the world gen pipeline this method should run. See {@link EDhApiDistantGeneratorMode} for additional documentation.
|
||||
* @param generatorMode how far into the world gen pipeline this method run. See {@link EDhApiDistantGeneratorMode} for additional documentation.
|
||||
*
|
||||
* @return See {@link IDhApiWorldGenerator#generateChunks(int, int, byte, byte, EDhApiDistantGeneratorMode, ExecutorService, Consumer) IDhApiWorldGenerator.generateChunks}
|
||||
* for the list of Object's this method should return along with additional documentation.
|
||||
@@ -122,21 +92,4 @@ public abstract class AbstractDhApiChunkWorldGenerator implements Closeable, IDh
|
||||
*/
|
||||
public abstract Object[] generateChunk(int chunkPosX, int chunkPosZ, EDhApiDistantGeneratorMode generatorMode);
|
||||
|
||||
/**
|
||||
* This method is called to generate terrain over a given area
|
||||
* from a thread defined by Distant Horizons. <br><br>
|
||||
*
|
||||
* @param chunkPosX the chunk X position in the level (not to be confused with the chunk's BlockPos in the level)
|
||||
* @param chunkPosZ the chunk Z position in the level (not to be confused with the chunk's BlockPos in the level)
|
||||
* @param generatorMode how far into the world gen pipeline this method should run. See {@link EDhApiDistantGeneratorMode} for additional documentation.
|
||||
*
|
||||
* @return A {@link DhApiChunk} with the generated {@link DhApiTerrainDataPoint} including air blocks.
|
||||
* Note: if air blocks aren't included with the proper lighting, lower detail levels will appear as black/unlit.
|
||||
*
|
||||
* @see IDhApiWorldGenerator#generateApiChunks(int, int, byte, byte, EDhApiDistantGeneratorMode, ExecutorService, Consumer)
|
||||
*
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
public abstract DhApiChunk generateApiChunk(int chunkPosX, int chunkPosZ, EDhApiDistantGeneratorMode generatorMode);
|
||||
|
||||
}
|
||||
|
||||
-1
@@ -154,7 +154,6 @@ public interface IDhApiWorldGenerator extends Closeable, IDhApiOverrideable
|
||||
*
|
||||
* After the {@link DhApiChunk} has been generated, it should be passed into the
|
||||
* resultConsumer's {@link Consumer#accept(Object)} method.
|
||||
* Note: if air blocks aren't included in the with the {@link DhApiChunk} with proper lighting, lower detail levels will appear as black/unlit.
|
||||
*
|
||||
* @implNote the default implementation of this method throws an {@link UnsupportedOperationException},
|
||||
* and must be overridden when {@link #getReturnType()} returns {@link EDhApiWorldGeneratorReturnType#API_CHUNKS}.
|
||||
|
||||
-67
@@ -1,67 +0,0 @@
|
||||
package com.seibel.distanthorizons.api.interfaces.render;
|
||||
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
|
||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Handles creating
|
||||
* {@link IDhApiRenderableBoxGroup} objects,
|
||||
* which can be added via a {@link IDhApiCustomRenderRegister}.
|
||||
*
|
||||
* @see IDhApiCustomRenderRegister
|
||||
* @see IDhApiRenderableBoxGroup
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 2024-7-3
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
public interface IDhApiCustomRenderObjectFactory
|
||||
{
|
||||
/**
|
||||
* Creates a {@link IDhApiRenderableBoxGroup} from for the given {@link DhApiRenderableBox}
|
||||
* where the box is positioned relative to the level's origin.
|
||||
*
|
||||
* @param resourceLocation A colon separated Resource Location string, similar to vanilla Minecraft, for example: "DistantHorizons:Clouds"
|
||||
*
|
||||
* @see DhApiRenderableBox
|
||||
* @see IDhApiRenderableBoxGroup#getResourceLocationNamespace()
|
||||
* @see IDhApiRenderableBoxGroup#getResourceLocationPath()
|
||||
*
|
||||
* @throws IllegalArgumentException if <code>resourceLocation</code> is null, isn't separated by a colon, or has multiple colons.
|
||||
*/
|
||||
IDhApiRenderableBoxGroup createForSingleBox(String resourceLocation, DhApiRenderableBox cube) throws IllegalArgumentException;
|
||||
|
||||
/**
|
||||
* Creates a {@link IDhApiRenderableBoxGroup} from the given list of {@link DhApiRenderableBox} where each
|
||||
* one is positioned relative to given <code>originBlockPos</code>, which in turn is relative to the level's origin.
|
||||
*
|
||||
* @param resourceLocation A colon separated Resource Location string, similar to vanilla Minecraft, for example: "DistantHorizons:Clouds"
|
||||
* @param originBlockPos The starting position for this {@link IDhApiRenderableBoxGroup}, can be changed during runtime.
|
||||
*
|
||||
*
|
||||
* @see DhApiRenderableBox
|
||||
* @see IDhApiRenderableBoxGroup#getResourceLocationNamespace()
|
||||
* @see IDhApiRenderableBoxGroup#getResourceLocationPath()
|
||||
*
|
||||
* @throws IllegalArgumentException if <code>resourceLocation</code> is null, isn't separated by a colon, or has multiple colons.
|
||||
*/
|
||||
IDhApiRenderableBoxGroup createRelativePositionedGroup(String resourceLocation, DhApiVec3d originBlockPos, List<DhApiRenderableBox> cubeList);
|
||||
|
||||
/**
|
||||
* Creates a {@link IDhApiRenderableBoxGroup} from the given list of {@link DhApiRenderableBox} where each
|
||||
* one is positioned relative to the level's origin.
|
||||
*
|
||||
* @param resourceLocation A colon separated Resource Location string, similar to vanilla Minecraft, for example: "DistantHorizons:Clouds"
|
||||
*
|
||||
* @see DhApiRenderableBox
|
||||
* @see IDhApiRenderableBoxGroup#getResourceLocationNamespace()
|
||||
* @see IDhApiRenderableBoxGroup#getResourceLocationPath()
|
||||
*
|
||||
* @throws IllegalArgumentException if <code>resourceLocation</code> is null, isn't separated by a colon, or has multiple colons.
|
||||
*/
|
||||
IDhApiRenderableBoxGroup createAbsolutePositionedGroup(String resourceLocation, List<DhApiRenderableBox> cubeList);
|
||||
|
||||
}
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
package com.seibel.distanthorizons.api.interfaces.render;
|
||||
|
||||
import com.seibel.distanthorizons.api.DhApi;
|
||||
import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
|
||||
import com.seibel.distanthorizons.api.interfaces.world.IDhApiWorldProxy;
|
||||
|
||||
/**
|
||||
* Handles adding and removing
|
||||
* {@link IDhApiRenderableBoxGroup} objects,
|
||||
* from DH's renderer. <br><br>
|
||||
*
|
||||
* Can be accessed in
|
||||
* {@link DhApi.Delayed#worldProxy} -> {@link IDhApiLevelWrapper}.
|
||||
*
|
||||
* @see IDhApiCustomRenderObjectFactory
|
||||
* @see IDhApiRenderableBoxGroup
|
||||
* @see IDhApiWorldProxy
|
||||
* @see IDhApiLevelWrapper
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 2024-7-3
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
public interface IDhApiCustomRenderRegister
|
||||
{
|
||||
void add(IDhApiRenderableBoxGroup cubeGroup) throws IllegalArgumentException;
|
||||
|
||||
IDhApiRenderableBoxGroup remove(long id);
|
||||
|
||||
}
|
||||
-98
@@ -1,98 +0,0 @@
|
||||
package com.seibel.distanthorizons.api.interfaces.render;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiLodShading;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3i;
|
||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
|
||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* A list of {@link DhApiRenderableBox}'s that
|
||||
* can be rendered to DH's terrain pass.
|
||||
*
|
||||
* @see DhApiRenderableBox
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 2024-6-30
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
public interface IDhApiRenderableBoxGroup extends List<DhApiRenderableBox>
|
||||
{
|
||||
/**
|
||||
* A unique numerical ID used by DH during rendering.
|
||||
* This can also be used to bind/unbind specific {@link IDhApiRenderableBoxGroup}'s from the renderer.
|
||||
* @return the ID for this specific group
|
||||
*/
|
||||
long getId();
|
||||
|
||||
/**
|
||||
* Used to determine which mods have added what to the DH renderer.
|
||||
* This can be used both by the F3 pie chart so you as a mod developer can profile your code
|
||||
* or by shader developers who want to render your objects differently. <br><br>
|
||||
*
|
||||
* Should be used the same as a vanilla Minecraft ResourceLocation.
|
||||
* For example if your mod named "Heavy Thunder" adds additional clouds named "Storm Front",
|
||||
* your Resource Location would be something like "HeavyThunder:StormFront"
|
||||
* and this method would return "HeavyThunder".
|
||||
*/
|
||||
String getResourceLocationNamespace();
|
||||
/**
|
||||
* Used to determine what type of object mods have added what to the DH renderer.
|
||||
* This can be used both by the F3 pie chart so you as a mod developer can profile your code
|
||||
* or by shader developers who want to render your objects differently. <br><br>
|
||||
*
|
||||
* Should be used the same as a vanilla Minecraft ResourceLocation.
|
||||
* For example if your mod named "Heavy Thunder" adds additional clouds named "Storm Front",
|
||||
* your Resource Location would be something like "HeavyThunder:StormFront"
|
||||
* and this method would return "StormFront".
|
||||
*/
|
||||
String getResourceLocationPath();
|
||||
|
||||
/** Sets whether this group should render or not. */
|
||||
void setActive(boolean active);
|
||||
/** @return if active this group will render. */
|
||||
boolean isActive();
|
||||
|
||||
/** Sets whether this group should render with Screen Space Ambient Occlusioning. */
|
||||
void setSsaoEnabled(boolean ssaoEnabled);
|
||||
/** @return if active this group will render with Screen Space Ambient Occlusioning. */
|
||||
boolean isSsaoEnabled();
|
||||
|
||||
/** Sets where this group will render in the level. */
|
||||
void setOriginBlockPos(DhApiVec3d pos);
|
||||
/** @return the block position in the level that all {@see DhApiRenderableBox} will render relative to. */
|
||||
DhApiVec3d getOriginBlockPos();
|
||||
|
||||
/**
|
||||
* Called right before this group is rendered. <br>
|
||||
* This is a good place to change the origin or notify of any box changes.
|
||||
*/
|
||||
void setPreRenderFunc(Consumer<DhApiRenderParam> renderEventParam);
|
||||
void setPostRenderFunc(Consumer<DhApiRenderParam> renderEventParam); // TODO name?
|
||||
|
||||
/**
|
||||
* If a cube's color, position, or other property is changed this method
|
||||
* must be called for those changes to render. <br><br>
|
||||
*
|
||||
* Note: changing the group's position via {@link #setOriginBlockPos} doesn't
|
||||
* require calling this method.
|
||||
*/
|
||||
void triggerBoxChange();
|
||||
|
||||
/** Only accepts values between 0 and 15 */
|
||||
void setSkyLight(int skyLight);
|
||||
int getSkyLight();
|
||||
|
||||
/** Only accepts values between 0 and 15 */
|
||||
void setBlockLight(int blockLight);
|
||||
int getBlockLight();
|
||||
|
||||
void setShading(DhApiRenderableBoxGroupShading shading);
|
||||
DhApiRenderableBoxGroupShading getShading();
|
||||
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
package com.seibel.distanthorizons.api.interfaces.util;
|
||||
|
||||
/**
|
||||
* Used for objects that need deep clones. <br>
|
||||
* Replacement for {@link Cloneable}.
|
||||
*
|
||||
* @see Cloneable
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 2024-7-12
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
public interface IDhApiCopyable
|
||||
{
|
||||
/** Returns a deep clone of all parameters whenever possible. */
|
||||
IDhApiCopyable copy();
|
||||
|
||||
}
|
||||
+1
-8
@@ -21,7 +21,6 @@ package com.seibel.distanthorizons.api.interfaces.world;
|
||||
|
||||
import com.seibel.distanthorizons.api.interfaces.IDhApiUnsafeWrapper;
|
||||
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiLevelType;
|
||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister;
|
||||
|
||||
/**
|
||||
* Can be either a Server or Client level.<br>
|
||||
@@ -44,7 +43,7 @@ public interface IDhApiLevelWrapper extends IDhApiUnsafeWrapper
|
||||
boolean hasSkyLight();
|
||||
|
||||
/** Returns the max block height of the level(?) */
|
||||
int getMaxHeight();
|
||||
int getHeight();
|
||||
|
||||
/**
|
||||
* Returns the lowest possible block position for the level. <br>
|
||||
@@ -52,10 +51,4 @@ public interface IDhApiLevelWrapper extends IDhApiUnsafeWrapper
|
||||
*/
|
||||
default int getMinHeight() { return 0; }
|
||||
|
||||
/**
|
||||
* Will return null if called on the server,
|
||||
* or if called before the renderer has been set up.
|
||||
*/
|
||||
IDhApiCustomRenderRegister getRenderRegister();
|
||||
|
||||
}
|
||||
+6
-9
@@ -26,20 +26,17 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp
|
||||
/**
|
||||
* Fired after Distant Horizons finishes rendering a frame. <br>
|
||||
* At this point DH will have also finished cleaning up any modifications it
|
||||
* did to the OpenGL state, so the state should be back to Minecraft's defaults. <br><br>
|
||||
* did to the OpenGL state, so the state should be back to Minecraft's defaults.
|
||||
*
|
||||
* Note: as of API v 3.0.0 no {@link DhApiRenderParam} is included in this event
|
||||
* because the specific parameters may change
|
||||
* depending on whether deferred rendering is enabled or not.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 2024-7-14
|
||||
* @version 2024-1-31
|
||||
* @see DhApiRenderParam
|
||||
* @since API 1.0.0
|
||||
*/
|
||||
public abstract class DhApiAfterRenderEvent implements IDhApiEvent<Void>
|
||||
public abstract class DhApiAfterRenderEvent implements IDhApiEvent<DhApiRenderParam>
|
||||
{
|
||||
/** Fired after Distant Horizons finishes rendering fake chunks. */
|
||||
public abstract void afterRender(DhApiEventParam<Void> event);
|
||||
public abstract void afterRender(DhApiEventParam<DhApiRenderParam> event);
|
||||
|
||||
|
||||
//=========================//
|
||||
@@ -47,6 +44,6 @@ public abstract class DhApiAfterRenderEvent implements IDhApiEvent<Void>
|
||||
//=========================//
|
||||
|
||||
@Override
|
||||
public final void fireEvent(DhApiEventParam<Void> event) { this.afterRender(event); }
|
||||
public final void fireEvent(DhApiEventParam<DhApiRenderParam> event) { this.afterRender(event); }
|
||||
|
||||
}
|
||||
+4
-14
@@ -20,10 +20,9 @@
|
||||
package com.seibel.distanthorizons.api.methods.events.abstractEvents;
|
||||
|
||||
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEventParam;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Vec3f;
|
||||
|
||||
/**
|
||||
* Called before Distant Horizons starts rendering a buffer. <br>
|
||||
@@ -53,29 +52,20 @@ public abstract class DhApiBeforeBufferRenderEvent implements IDhApiEvent<DhApiB
|
||||
// parameter object //
|
||||
//==================//
|
||||
|
||||
public static class EventParam extends DhApiRenderParam implements IDhApiEventParam
|
||||
public static class EventParam extends DhApiRenderParam
|
||||
{
|
||||
/**
|
||||
* Measured in blocks.
|
||||
* Should be applied to the model view matrix to move the buffer into its proper place.
|
||||
*/
|
||||
public final DhApiVec3f modelPos;
|
||||
public final Vec3f modelPos;
|
||||
|
||||
|
||||
public EventParam(DhApiRenderParam parent, DhApiVec3f modelPos)
|
||||
public EventParam(DhApiRenderParam parent, Vec3f modelPos)
|
||||
{
|
||||
super(parent);
|
||||
this.modelPos = modelPos;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public EventParam copy()
|
||||
{
|
||||
return new EventParam(
|
||||
this, this.modelPos.copy()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-97
@@ -1,97 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2023 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.api.methods.events.abstractEvents;
|
||||
|
||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
|
||||
import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
|
||||
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiCancelableEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEventParam;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiCancelableEventParam;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
|
||||
|
||||
/**
|
||||
* Called before Distant Horizons starts rendering a generic object. <br>
|
||||
* Canceling this event will prevent the triggering {@link IDhApiRenderableBoxGroup} from rendering this frame.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 2024-7-11
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
public abstract class DhApiBeforeGenericObjectRenderEvent implements IDhApiCancelableEvent<DhApiBeforeGenericObjectRenderEvent.EventParam>
|
||||
{
|
||||
/** Fired before Distant Horizons renders a generic object. */
|
||||
public abstract void beforeRender(DhApiCancelableEventParam<EventParam> event);
|
||||
|
||||
|
||||
//=========================//
|
||||
// internal DH API methods //
|
||||
//=========================//
|
||||
|
||||
@Override
|
||||
public final void fireEvent(DhApiCancelableEventParam<EventParam> input) { this.beforeRender(input); }
|
||||
|
||||
|
||||
//==================//
|
||||
// parameter object //
|
||||
//==================//
|
||||
|
||||
public static class EventParam extends DhApiRenderParam implements IDhApiEventParam
|
||||
{
|
||||
public final long boxGroupId;
|
||||
public final String resourceLocationNamespace;
|
||||
public final String resourceLocationPath;
|
||||
|
||||
|
||||
public EventParam(
|
||||
DhApiRenderParam renderParam,
|
||||
IDhApiRenderableBoxGroup boxGroup
|
||||
)
|
||||
{
|
||||
super(renderParam);
|
||||
|
||||
this.boxGroupId = boxGroup.getId();
|
||||
this.resourceLocationNamespace = boxGroup.getResourceLocationNamespace();
|
||||
this.resourceLocationPath = boxGroup.getResourceLocationPath();
|
||||
}
|
||||
public EventParam(
|
||||
DhApiRenderParam renderParam,
|
||||
long boxGroupId, String resourceLocationNamespace, String resourceLocationPath
|
||||
)
|
||||
{
|
||||
super(renderParam);
|
||||
|
||||
this.boxGroupId = boxGroupId;
|
||||
this.resourceLocationNamespace = resourceLocationNamespace;
|
||||
this.resourceLocationPath = resourceLocationPath;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public EventParam copy()
|
||||
{
|
||||
return new EventParam(
|
||||
this,
|
||||
this.boxGroupId, this.resourceLocationNamespace, this.resourceLocationPath
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2023 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.api.methods.events.abstractEvents;
|
||||
|
||||
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
|
||||
|
||||
/**
|
||||
* Called before Distant Horizons starts the cleanup process done after rendering generic objects. <br>
|
||||
* This is called after all generic objects have finished rendering.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 2024-7-13
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
public abstract class DhApiBeforeGenericRenderCleanupEvent implements IDhApiEvent<DhApiRenderParam>
|
||||
{
|
||||
/** Fired before Distant Horizons starts the cleanup process once rendering has finished. */
|
||||
public abstract void beforeCleanup(DhApiEventParam<DhApiRenderParam> event);
|
||||
|
||||
|
||||
//=========================//
|
||||
// internal DH API methods //
|
||||
//=========================//
|
||||
|
||||
@Override
|
||||
public final void fireEvent(DhApiEventParam<DhApiRenderParam> event) { this.beforeCleanup(event); }
|
||||
|
||||
}
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2023 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.api.methods.events.abstractEvents;
|
||||
|
||||
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
|
||||
|
||||
/**
|
||||
* Called before Distant Horizons has started setting up OpenGL objects for rendering generic objects. <br>
|
||||
* If you want to modify already bound DH OpenGL objects try using {@link DhApiBeforeGenericObjectRenderEvent}.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 2024-7-12
|
||||
* @since API 3.0.0
|
||||
*
|
||||
* @see DhApiBeforeGenericObjectRenderEvent
|
||||
*/
|
||||
public abstract class DhApiBeforeGenericRenderSetupEvent implements IDhApiEvent<DhApiRenderParam>
|
||||
{
|
||||
/** Fired before Distant Horizons has started setting up OpenGL objects for rendering generic objects. */
|
||||
public abstract void beforeSetup(DhApiEventParam<DhApiRenderParam> input);
|
||||
|
||||
|
||||
//=========================//
|
||||
// internal DH API methods //
|
||||
//=========================//
|
||||
|
||||
@Override
|
||||
public final void fireEvent(DhApiEventParam<DhApiRenderParam> input) { this.beforeSetup(input); }
|
||||
|
||||
|
||||
}
|
||||
+1
-1
@@ -33,7 +33,7 @@ import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhAp
|
||||
*/
|
||||
public abstract class DhApiBeforeRenderCleanupEvent implements IDhApiEvent<DhApiRenderParam>
|
||||
{
|
||||
/** Fired before Distant Horizons starts the cleanup process once rendering has finished. */
|
||||
/** Fired before Distant Horizons renders LODs. */
|
||||
public abstract void beforeCleanup(DhApiEventParam<DhApiRenderParam> event);
|
||||
|
||||
|
||||
|
||||
+1
-11
@@ -22,7 +22,6 @@ package com.seibel.distanthorizons.api.methods.events.abstractEvents;
|
||||
import com.seibel.distanthorizons.api.interfaces.data.IDhApiTerrainDataRepo;
|
||||
import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
|
||||
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEventParam;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam;
|
||||
|
||||
/**
|
||||
@@ -54,7 +53,7 @@ public abstract class DhApiChunkModifiedEvent implements IDhApiEvent<DhApiChunkM
|
||||
// parameter object //
|
||||
//==================//
|
||||
|
||||
public static class EventParam implements IDhApiEventParam
|
||||
public static class EventParam
|
||||
{
|
||||
/** The saved level. */
|
||||
public final IDhApiLevelWrapper levelWrapper;
|
||||
@@ -72,15 +71,6 @@ public abstract class DhApiChunkModifiedEvent implements IDhApiEvent<DhApiChunkM
|
||||
this.chunkZ = chunkZ;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public EventParam copy()
|
||||
{
|
||||
return new EventParam(
|
||||
this.levelWrapper,
|
||||
this.chunkX, this.chunkZ
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+1
-12
@@ -20,7 +20,6 @@
|
||||
package com.seibel.distanthorizons.api.methods.events.abstractEvents;
|
||||
|
||||
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEventParam;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam;
|
||||
|
||||
/**
|
||||
@@ -49,7 +48,7 @@ public abstract class DhApiColorDepthTextureCreatedEvent implements IDhApiEvent<
|
||||
// parameter object //
|
||||
//==================//
|
||||
|
||||
public static class EventParam implements IDhApiEventParam
|
||||
public static class EventParam
|
||||
{
|
||||
/** Measured in pixels */
|
||||
public final int previousWidth;
|
||||
@@ -73,16 +72,6 @@ public abstract class DhApiColorDepthTextureCreatedEvent implements IDhApiEvent<
|
||||
this.newHeight = newHeight;
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public EventParam copy()
|
||||
{
|
||||
return new EventParam(
|
||||
this.previousWidth, this.previousHeight,
|
||||
this.newWidth, this.newHeight
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+1
-5
@@ -21,7 +21,6 @@ package com.seibel.distanthorizons.api.methods.events.abstractEvents;
|
||||
|
||||
import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
|
||||
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEventParam;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam;
|
||||
|
||||
/**
|
||||
@@ -50,16 +49,13 @@ public abstract class DhApiLevelLoadEvent implements IDhApiEvent<DhApiLevelLoadE
|
||||
// parameter object //
|
||||
//==================//
|
||||
|
||||
public static class EventParam implements IDhApiEventParam
|
||||
public static class EventParam
|
||||
{
|
||||
/** The newly loaded level. */
|
||||
public final IDhApiLevelWrapper levelWrapper;
|
||||
|
||||
public EventParam(IDhApiLevelWrapper newLevelWrapper) { this.levelWrapper = newLevelWrapper; }
|
||||
|
||||
|
||||
@Override
|
||||
public EventParam copy() { return new EventParam(this.levelWrapper); }
|
||||
}
|
||||
|
||||
}
|
||||
+2
-5
@@ -19,9 +19,9 @@
|
||||
|
||||
package com.seibel.distanthorizons.api.methods.events.abstractEvents;
|
||||
|
||||
import com.seibel.distanthorizons.api.DhApi;
|
||||
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent;
|
||||
import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
|
||||
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEventParam;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam;
|
||||
|
||||
/**
|
||||
@@ -49,16 +49,13 @@ public abstract class DhApiLevelUnloadEvent implements IDhApiEvent<DhApiLevelUnl
|
||||
// parameter object //
|
||||
//==================//
|
||||
|
||||
public static class EventParam implements IDhApiEventParam
|
||||
public static class EventParam
|
||||
{
|
||||
/** The recently unloaded level. */
|
||||
public final IDhApiLevelWrapper levelWrapper;
|
||||
|
||||
public EventParam(IDhApiLevelWrapper newLevelWrapper) { this.levelWrapper = newLevelWrapper; }
|
||||
|
||||
|
||||
@Override
|
||||
public EventParam copy() { return new EventParam(this.levelWrapper); }
|
||||
}
|
||||
|
||||
}
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
package com.seibel.distanthorizons.api.methods.events.interfaces;
|
||||
|
||||
import com.seibel.distanthorizons.api.interfaces.util.IDhApiCopyable;
|
||||
|
||||
/**
|
||||
* @author James Seibel
|
||||
* @version 2024-7-12
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
public interface IDhApiEventParam extends IDhApiCopyable
|
||||
{
|
||||
|
||||
}
|
||||
+16
-29
@@ -20,8 +20,7 @@
|
||||
package com.seibel.distanthorizons.api.methods.events.sharedParameterObjects;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiRenderPass;
|
||||
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEventParam;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
|
||||
|
||||
/**
|
||||
* Contains information relevant to Distant Horizons and Minecraft rendering.
|
||||
@@ -30,7 +29,7 @@ import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
|
||||
* @version 2024-1-31
|
||||
* @since API 1.0.0
|
||||
*/
|
||||
public class DhApiRenderParam implements IDhApiEventParam
|
||||
public class DhApiRenderParam
|
||||
{
|
||||
/** Indicates what render pass DH is currently rendering */
|
||||
public final EDhApiRenderPass renderPass;
|
||||
@@ -50,14 +49,14 @@ public class DhApiRenderParam implements IDhApiEventParam
|
||||
public final float farClipPlane;
|
||||
|
||||
/** The projection matrix Minecraft is using to render this frame. */
|
||||
public final DhApiMat4f mcProjectionMatrix;
|
||||
public final Mat4f mcProjectionMatrix;
|
||||
/** The model view matrix Minecraft is using to render this frame. */
|
||||
public final DhApiMat4f mcModelViewMatrix;
|
||||
public final Mat4f mcModelViewMatrix;
|
||||
|
||||
/** The projection matrix Distant Horizons is using to render this frame. */
|
||||
public final DhApiMat4f dhProjectionMatrix;
|
||||
public final Mat4f dhProjectionMatrix;
|
||||
/** The model view matrix Distant Horizons is using to render this frame. */
|
||||
public final DhApiMat4f dhModelViewMatrix;
|
||||
public final Mat4f dhModelViewMatrix;
|
||||
|
||||
public final int worldYOffset;
|
||||
|
||||
@@ -67,24 +66,24 @@ public class DhApiRenderParam implements IDhApiEventParam
|
||||
// constructors //
|
||||
//==============//
|
||||
|
||||
|
||||
public DhApiRenderParam(DhApiRenderParam parent)
|
||||
{
|
||||
this(
|
||||
parent.renderPass,
|
||||
parent.partialTicks,
|
||||
parent.nearClipPlane, parent.farClipPlane,
|
||||
parent.mcProjectionMatrix.copy(), parent.mcModelViewMatrix.copy(),
|
||||
parent.dhProjectionMatrix.copy(), parent.dhModelViewMatrix.copy(),
|
||||
parent.worldYOffset
|
||||
);
|
||||
parent.renderPass,
|
||||
parent.partialTicks,
|
||||
parent.nearClipPlane, parent.farClipPlane,
|
||||
parent.mcProjectionMatrix, parent.mcModelViewMatrix,
|
||||
parent.dhProjectionMatrix, parent.dhModelViewMatrix,
|
||||
parent.worldYOffset
|
||||
);
|
||||
}
|
||||
|
||||
public DhApiRenderParam(
|
||||
EDhApiRenderPass renderPass,
|
||||
float newPartialTicks,
|
||||
float nearClipPlane, float farClipPlane,
|
||||
DhApiMat4f newMcProjectionMatrix, DhApiMat4f newMcModelViewMatrix,
|
||||
DhApiMat4f newDhProjectionMatrix, DhApiMat4f newDhModelViewMatrix,
|
||||
Mat4f newMcProjectionMatrix, Mat4f newMcModelViewMatrix,
|
||||
Mat4f newDhProjectionMatrix, Mat4f newDhModelViewMatrix,
|
||||
int worldYOffset
|
||||
)
|
||||
{
|
||||
@@ -105,16 +104,4 @@ public class DhApiRenderParam implements IDhApiEventParam
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// base overrides //
|
||||
//================//
|
||||
|
||||
@Override
|
||||
public DhApiRenderParam copy()
|
||||
{
|
||||
return new DhApiRenderParam(this);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ import java.util.List;
|
||||
* Contains a list of {@link DhApiTerrainDataPoint} representing the blocks in a Minecraft chunk.
|
||||
*
|
||||
* @author Builderb0y, James Seibel
|
||||
* @version 2024-7-21
|
||||
* @version 2023-12-21
|
||||
* @since API 2.0.0
|
||||
*
|
||||
* @see IDhApiWrapperFactory
|
||||
@@ -41,8 +41,8 @@ public class DhApiChunk
|
||||
public final int chunkPosX;
|
||||
public final int chunkPosZ;
|
||||
|
||||
public final int bottomYBlockPos;
|
||||
public final int topYBlockPos;
|
||||
public final int bottomYBlockPos;
|
||||
|
||||
private final List<List<DhApiTerrainDataPoint>> dataPoints;
|
||||
|
||||
@@ -52,12 +52,12 @@ public class DhApiChunk
|
||||
// constructors //
|
||||
//==============//
|
||||
|
||||
public DhApiChunk(int chunkPosX, int chunkPosZ, int bottomYBlockPos, int topYBlockPos)
|
||||
public DhApiChunk(int chunkPosX, int chunkPosZ, int topYBlockPos, int bottomYBlockPos)
|
||||
{
|
||||
this.chunkPosX = chunkPosX;
|
||||
this.chunkPosZ = chunkPosZ;
|
||||
this.bottomYBlockPos = bottomYBlockPos;
|
||||
this.topYBlockPos = topYBlockPos;
|
||||
this.bottomYBlockPos = bottomYBlockPos;
|
||||
|
||||
// populate the array to prevent null pointers
|
||||
this.dataPoints = new ArrayList<>(16 * 16); // 256
|
||||
|
||||
+2
-1
@@ -20,6 +20,7 @@
|
||||
package com.seibel.distanthorizons.api.objects.data;
|
||||
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3i;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Vec3i;
|
||||
|
||||
/**
|
||||
* Holds a single datapoint of terrain data
|
||||
@@ -46,7 +47,7 @@ public class DhApiRaycastResult
|
||||
|
||||
|
||||
|
||||
public DhApiRaycastResult(DhApiTerrainDataPoint dataPoint, DhApiVec3i blockPos)
|
||||
public DhApiRaycastResult(DhApiTerrainDataPoint dataPoint, Vec3i blockPos)
|
||||
{
|
||||
this.dataPoint = dataPoint;
|
||||
this.pos = blockPos;
|
||||
|
||||
+4
-4
@@ -26,7 +26,7 @@ import com.seibel.distanthorizons.api.interfaces.block.IDhApiBlockStateWrapper;
|
||||
* Holds a single datapoint of terrain data.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 2024-7-20
|
||||
* @version 2022-11-13
|
||||
* @since API 1.0.0
|
||||
*/
|
||||
public class DhApiTerrainDataPoint
|
||||
@@ -42,22 +42,22 @@ public class DhApiTerrainDataPoint
|
||||
|
||||
public final int blockLightLevel;
|
||||
public final int skyLightLevel;
|
||||
public final int bottomYBlockPos;
|
||||
public final int topYBlockPos;
|
||||
public final int bottomYBlockPos;
|
||||
|
||||
public final IDhApiBlockStateWrapper blockStateWrapper;
|
||||
public final IDhApiBiomeWrapper biomeWrapper;
|
||||
|
||||
|
||||
|
||||
public DhApiTerrainDataPoint(byte detailLevel, int blockLightLevel, int skyLightLevel, int bottomYBlockPos, int topYBlockPos, IDhApiBlockStateWrapper blockStateWrapper, IDhApiBiomeWrapper biomeWrapper)
|
||||
public DhApiTerrainDataPoint(byte detailLevel, int blockLightLevel, int skyLightLevel, int topYBlockPos, int bottomYBlockPos, IDhApiBlockStateWrapper blockStateWrapper, IDhApiBiomeWrapper biomeWrapper)
|
||||
{
|
||||
this.detailLevel = detailLevel;
|
||||
|
||||
this.blockLightLevel = blockLightLevel;
|
||||
this.skyLightLevel = skyLightLevel;
|
||||
this.bottomYBlockPos = bottomYBlockPos;
|
||||
this.topYBlockPos = topYBlockPos;
|
||||
this.bottomYBlockPos = bottomYBlockPos;
|
||||
|
||||
this.blockStateWrapper = blockStateWrapper;
|
||||
this.biomeWrapper = biomeWrapper;
|
||||
|
||||
@@ -1,94 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2023 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.api.objects.math;
|
||||
|
||||
/**
|
||||
* Often used to store block positions or any other
|
||||
* position in 3D space.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 2024-7-9
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
public class DhApiVec3d
|
||||
{
|
||||
public double x;
|
||||
public double y;
|
||||
public double z;
|
||||
|
||||
|
||||
|
||||
/** creates a Vec3 at (0,0,0) */
|
||||
public DhApiVec3d()
|
||||
{
|
||||
this.x = 0;
|
||||
this.y = 0;
|
||||
this.z = 0;
|
||||
}
|
||||
|
||||
public DhApiVec3d(double x, double y, double z)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (obj != null && this.getClass() == obj.getClass())
|
||||
{
|
||||
DhApiVec3d Vec3d = (DhApiVec3d) obj;
|
||||
if (Double.compare(Vec3d.x, this.x) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (Double.compare(Vec3d.y, this.y) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Double.compare(Vec3d.z, this.z) == 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
long i = Double.doubleToLongBits(this.x);
|
||||
i = 31 * i + Double.doubleToLongBits(this.y);
|
||||
i = 31 * i + Double.doubleToLongBits(this.z);
|
||||
return Long.hashCode(i);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() { return "[" + this.x + ", " + this.y + ", " + this.z + "]"; }
|
||||
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2023 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.api.objects.math;
|
||||
|
||||
import com.seibel.distanthorizons.api.interfaces.util.IDhApiCopyable;
|
||||
|
||||
/**
|
||||
* Often used to store block positions or any other
|
||||
* position in 3D space.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 2024-6-3
|
||||
* @since API 2.2.0
|
||||
*/
|
||||
public class DhApiVec3f implements IDhApiCopyable
|
||||
{
|
||||
public float x;
|
||||
public float y;
|
||||
public float z;
|
||||
|
||||
|
||||
|
||||
/** creates a Vec3 at (0,0,0) */
|
||||
public DhApiVec3f()
|
||||
{
|
||||
this.x = 0;
|
||||
this.y = 0;
|
||||
this.z = 0;
|
||||
}
|
||||
|
||||
public DhApiVec3f(float x, float y, float z)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (obj != null && this.getClass() == obj.getClass())
|
||||
{
|
||||
DhApiVec3f Vec3f = (DhApiVec3f) obj;
|
||||
if (Float.compare(Vec3f.x, this.x) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (Float.compare(Vec3f.y, this.y) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Float.compare(Vec3f.z, this.z) == 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int i = Float.floatToIntBits(this.x);
|
||||
i = 31 * i + Float.floatToIntBits(this.y);
|
||||
return 31 * i + Float.floatToIntBits(this.z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() { return "[" + this.x + ", " + this.y + ", " + this.z + "]"; }
|
||||
|
||||
@Override
|
||||
public DhApiVec3f copy() { return new DhApiVec3f(this.x, this.y, this.z); }
|
||||
|
||||
}
|
||||
-52
@@ -1,52 +0,0 @@
|
||||
package com.seibel.distanthorizons.api.objects.render;
|
||||
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial;
|
||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* @see IDhApiRenderableBoxGroup
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 2024-6-30
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
public class DhApiRenderableBox
|
||||
{
|
||||
/** the position closest to (-inf,-inf) */
|
||||
public DhApiVec3d minPos;
|
||||
/** the position closest to (+inf,+inf) */
|
||||
public DhApiVec3d maxPos;
|
||||
|
||||
public Color color;
|
||||
public byte material;
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// constructors //
|
||||
//==============//
|
||||
|
||||
public DhApiRenderableBox(DhApiVec3d minPos, float width, Color color, EDhApiBlockMaterial material)
|
||||
{
|
||||
this(minPos, new DhApiVec3d(
|
||||
minPos.x + width,
|
||||
minPos.y + width,
|
||||
minPos.z + width
|
||||
), color, material);
|
||||
}
|
||||
|
||||
public DhApiRenderableBox(DhApiVec3d minPos, DhApiVec3d maxPos, Color color, EDhApiBlockMaterial material)
|
||||
{
|
||||
this.minPos = minPos;
|
||||
this.maxPos = maxPos;
|
||||
this.color = color;
|
||||
this.material = material.index;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-93
@@ -1,93 +0,0 @@
|
||||
package com.seibel.distanthorizons.api.objects.render;
|
||||
|
||||
|
||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
/**
|
||||
* @see IDhApiRenderableBoxGroup
|
||||
*
|
||||
* Shading values are multiplied against the color for each direction,
|
||||
* for example: <br>
|
||||
* A shading value of 1.0 indicates the color is unchanged. <br>
|
||||
* A shading value of 0.0 changes the color to black. <br>
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 2024-7-7
|
||||
* @since API 3.0.0
|
||||
*/
|
||||
public class DhApiRenderableBoxGroupShading
|
||||
{
|
||||
/** negative X */
|
||||
public float north = 1.0f;
|
||||
/** positive X */
|
||||
public float south = 1.0f;
|
||||
|
||||
/** positive X */
|
||||
public float east = 1.0f;
|
||||
/** negative X */
|
||||
public float west = 1.0f;
|
||||
|
||||
/** positive Y */
|
||||
public float top = 1.0f;
|
||||
/** negative Y */
|
||||
public float bottom = 1.0f;
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// constructors //
|
||||
//==============//
|
||||
|
||||
public static DhApiRenderableBoxGroupShading getDefaultShaded()
|
||||
{
|
||||
DhApiRenderableBoxGroupShading shading = new DhApiRenderableBoxGroupShading();
|
||||
shading.setDefaultShaded();
|
||||
return shading;
|
||||
}
|
||||
|
||||
public static DhApiRenderableBoxGroupShading getUnshaded()
|
||||
{
|
||||
DhApiRenderableBoxGroupShading shading = new DhApiRenderableBoxGroupShading();
|
||||
shading.setUnshaded();
|
||||
return shading;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// methods //
|
||||
//=========//
|
||||
|
||||
/**
|
||||
* Directions will have different brightness similar to Minecraft blocks. <br>
|
||||
* This is a good default for un-lit objects.
|
||||
*/
|
||||
public void setDefaultShaded()
|
||||
{
|
||||
this.north = 0.8f;
|
||||
this.south = 0.8f;
|
||||
this.east = 0.6f;
|
||||
this.west = 0.6f;
|
||||
this.top = 1.0f;
|
||||
this.bottom = 0.5f;
|
||||
}
|
||||
|
||||
/**
|
||||
* All directions render with the same brightness. <br>
|
||||
* This is best used for glowing objects like beacons.
|
||||
*/
|
||||
public void setUnshaded()
|
||||
{
|
||||
this.north = 1.0f;
|
||||
this.south = 1.0f;
|
||||
this.east = 1.0f;
|
||||
this.west = 1.0f;
|
||||
this.top = 1.0f;
|
||||
this.bottom = 1.0f;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+1
-21
@@ -22,7 +22,6 @@ package com.seibel.distanthorizons.coreapi.DependencyInjection;
|
||||
import com.seibel.distanthorizons.api.interfaces.events.IDhApiEventInjector;
|
||||
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiCancelableEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiEventParam;
|
||||
import com.seibel.distanthorizons.api.methods.events.interfaces.IDhApiOneTimeEvent;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiCancelableEventParam;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam;
|
||||
@@ -141,26 +140,7 @@ public class ApiEventInjector extends DependencyInjector<IDhApiEvent> implements
|
||||
// fire each event and record if any of them
|
||||
// request to cancel the event.
|
||||
|
||||
|
||||
// attempt to clone the event input if possible
|
||||
// this is done to reduce the likely hood that one event listener
|
||||
// will make change the event parameter for other listeners
|
||||
T input = eventInput;
|
||||
if (eventInput instanceof IDhApiEventParam)
|
||||
{
|
||||
try
|
||||
{
|
||||
//noinspection unchecked
|
||||
input = (T) ((IDhApiEventParam) eventInput).copy();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.error("Unable to clone event parameter ["+eventInput.getClass().getSimpleName()+"], error: ["+e.getMessage()+"].", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
DhApiEventParam<T> eventParam = createEventParamWrapper(event, input);
|
||||
DhApiEventParam<T> eventParam = createEventParamWrapper(event, eventInput);
|
||||
event.fireEvent(eventParam);
|
||||
|
||||
if (eventParam instanceof DhApiCancelableEventParam)
|
||||
|
||||
@@ -47,9 +47,9 @@ public final class ModInfo
|
||||
public static boolean IS_DEV_BUILD = VERSION.toLowerCase().contains("dev");
|
||||
|
||||
/** This version should only be updated when breaking changes are introduced to the DH API */
|
||||
public static final int API_MAJOR_VERSION = 3;
|
||||
public static final int API_MAJOR_VERSION = 2;
|
||||
/** This version should be updated whenever new methods are added to the DH API */
|
||||
public static final int API_MINOR_VERSION = 0;
|
||||
public static final int API_MINOR_VERSION = 1;
|
||||
/** This version should be updated whenever non-breaking fixes are added to the DH API */
|
||||
public static final int API_PATH_VERSION = 0;
|
||||
|
||||
|
||||
+1
-2
@@ -67,11 +67,10 @@ public interface IConfigEntry<T>
|
||||
* Checks if the option is valid
|
||||
*
|
||||
* 0 == valid
|
||||
* 2 == invalid
|
||||
* 1 == number too high
|
||||
* -1 == number too low
|
||||
*/
|
||||
byte isValid(); // TODO replace with an enum
|
||||
byte isValid();
|
||||
/** Checks if a value is valid */
|
||||
byte isValid(T value);
|
||||
|
||||
|
||||
+360
-126
@@ -17,55 +17,46 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.api.objects.math;
|
||||
package com.seibel.distanthorizons.coreapi.util.math;
|
||||
|
||||
import com.seibel.distanthorizons.api.interfaces.util.IDhApiCopyable;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Matrix4fc;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
/**
|
||||
* An (almost) exact copy of Minecraft's 1.16.5
|
||||
* implementation of a 4x4 float matrix. <br><br>
|
||||
* implementation of a 4x4 float matrix.
|
||||
*
|
||||
* <code>
|
||||
* m00, m10, m20, m30, <br>
|
||||
* m01, m11, m21, m31, <br>
|
||||
* m02, m12, m22, m32, <br>
|
||||
* m03, m13, m23, m33 <br>
|
||||
* </code>
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 2024-6-30
|
||||
* @version 11-11-2021
|
||||
*/
|
||||
public class DhApiMat4f implements IDhApiCopyable
|
||||
public class Mat4f
|
||||
{
|
||||
public float m00;
|
||||
public float m01;
|
||||
public float m02;
|
||||
public float m03;
|
||||
|
||||
public float m10;
|
||||
public float m11;
|
||||
public float m12;
|
||||
public float m13;
|
||||
|
||||
public float m20;
|
||||
public float m21;
|
||||
public float m22;
|
||||
public float m23;
|
||||
|
||||
public float m30;
|
||||
public float m31;
|
||||
public float m32;
|
||||
public float m33;
|
||||
private float m00;
|
||||
private float m01;
|
||||
private float m02;
|
||||
private float m03;
|
||||
private float m10;
|
||||
private float m11;
|
||||
private float m12;
|
||||
private float m13;
|
||||
private float m20;
|
||||
private float m21;
|
||||
private float m22;
|
||||
private float m23;
|
||||
private float m30;
|
||||
private float m31;
|
||||
private float m32;
|
||||
private float m33;
|
||||
|
||||
|
||||
public Mat4f()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//==============//
|
||||
// constructors //
|
||||
//==============//
|
||||
|
||||
public DhApiMat4f() { /* all values are 0 */ }
|
||||
|
||||
public DhApiMat4f(DhApiMat4f sourceMatrix)
|
||||
public Mat4f(Mat4f sourceMatrix)
|
||||
{
|
||||
this.m00 = sourceMatrix.m00;
|
||||
this.m01 = sourceMatrix.m01;
|
||||
@@ -85,36 +76,163 @@ public class DhApiMat4f implements IDhApiCopyable
|
||||
this.m33 = sourceMatrix.m33;
|
||||
}
|
||||
|
||||
/** Expects the values of the input array to be in row major order (AKA rows then columns) */
|
||||
public DhApiMat4f(float[] values)
|
||||
public Mat4f(Matrix4fc sourceMatrix) { this(convertJomlMatrixToArray(sourceMatrix)); }
|
||||
private static float[] convertJomlMatrixToArray(Matrix4fc sourceMatrix)
|
||||
{
|
||||
m00 = values[0];
|
||||
m01 = values[1];
|
||||
m02 = values[2];
|
||||
m03 = values[3];
|
||||
FloatBuffer buffer = FloatBuffer.allocate(16);
|
||||
|
||||
m10 = values[4];
|
||||
m11 = values[5];
|
||||
m12 = values[6];
|
||||
m13 = values[7];
|
||||
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());
|
||||
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());
|
||||
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());
|
||||
|
||||
m20 = values[8];
|
||||
m21 = values[9];
|
||||
m22 = values[10];
|
||||
m23 = values[11];
|
||||
|
||||
m30 = values[12];
|
||||
m31 = values[13];
|
||||
m32 = values[14];
|
||||
m33 = values[15];
|
||||
return buffer.array();
|
||||
}
|
||||
|
||||
/* Quaternions are not currently needed/implemented
|
||||
public Matrix4float(Quaternion p_i48104_1_)
|
||||
{
|
||||
float f = p_i48104_1_.i();
|
||||
float f1 = p_i48104_1_.j();
|
||||
float f2 = p_i48104_1_.k();
|
||||
float f3 = p_i48104_1_.r();
|
||||
float f4 = 2.0F * f * f;
|
||||
float f5 = 2.0F * f1 * f1;
|
||||
float f6 = 2.0F * f2 * f2;
|
||||
this.m00 = 1.0F - f5 - f6;
|
||||
this.m11 = 1.0F - f6 - f4;
|
||||
this.m22 = 1.0F - f4 - f5;
|
||||
this.m33 = 1.0F;
|
||||
float f7 = f * f1;
|
||||
float f8 = f1 * f2;
|
||||
float f9 = f2 * f;
|
||||
float f10 = f * f3;
|
||||
float f11 = f1 * f3;
|
||||
float f12 = f2 * f3;
|
||||
this.m10 = 2.0F * (f7 + f12);
|
||||
this.m01 = 2.0F * (f7 - f12);
|
||||
this.m20 = 2.0F * (f9 - f11);
|
||||
this.m02 = 2.0F * (f9 + f11);
|
||||
this.m21 = 2.0F * (f8 + f10);
|
||||
this.m12 = 2.0F * (f8 - f10);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (obj != null && this.getClass() == obj.getClass())
|
||||
{
|
||||
Mat4f otherMatrix = (Mat4f) obj;
|
||||
return Float.compare(otherMatrix.m00, this.m00) == 0
|
||||
&& Float.compare(otherMatrix.m01, this.m01) == 0
|
||||
&& Float.compare(otherMatrix.m02, this.m02) == 0
|
||||
&& Float.compare(otherMatrix.m03, this.m03) == 0
|
||||
&& Float.compare(otherMatrix.m10, this.m10) == 0
|
||||
&& Float.compare(otherMatrix.m11, this.m11) == 0
|
||||
&& Float.compare(otherMatrix.m12, this.m12) == 0
|
||||
&& Float.compare(otherMatrix.m13, this.m13) == 0
|
||||
&& Float.compare(otherMatrix.m20, this.m20) == 0
|
||||
&& Float.compare(otherMatrix.m21, this.m21) == 0
|
||||
&& Float.compare(otherMatrix.m22, this.m22) == 0
|
||||
&& Float.compare(otherMatrix.m23, this.m23) == 0
|
||||
&& Float.compare(otherMatrix.m30, this.m30) == 0
|
||||
&& Float.compare(otherMatrix.m31, this.m31) == 0
|
||||
&& Float.compare(otherMatrix.m32, this.m32) == 0
|
||||
&& Float.compare(otherMatrix.m33, this.m33) == 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int i = this.m00 != 0.0F ? Float.floatToIntBits(this.m00) : 0;
|
||||
i = 31 * i + (this.m01 != 0.0F ? Float.floatToIntBits(this.m01) : 0);
|
||||
i = 31 * i + (this.m02 != 0.0F ? Float.floatToIntBits(this.m02) : 0);
|
||||
i = 31 * i + (this.m03 != 0.0F ? Float.floatToIntBits(this.m03) : 0);
|
||||
i = 31 * i + (this.m10 != 0.0F ? Float.floatToIntBits(this.m10) : 0);
|
||||
i = 31 * i + (this.m11 != 0.0F ? Float.floatToIntBits(this.m11) : 0);
|
||||
i = 31 * i + (this.m12 != 0.0F ? Float.floatToIntBits(this.m12) : 0);
|
||||
i = 31 * i + (this.m13 != 0.0F ? Float.floatToIntBits(this.m13) : 0);
|
||||
i = 31 * i + (this.m20 != 0.0F ? Float.floatToIntBits(this.m20) : 0);
|
||||
i = 31 * i + (this.m21 != 0.0F ? Float.floatToIntBits(this.m21) : 0);
|
||||
i = 31 * i + (this.m22 != 0.0F ? Float.floatToIntBits(this.m22) : 0);
|
||||
i = 31 * i + (this.m23 != 0.0F ? Float.floatToIntBits(this.m23) : 0);
|
||||
i = 31 * i + (this.m30 != 0.0F ? Float.floatToIntBits(this.m30) : 0);
|
||||
i = 31 * i + (this.m31 != 0.0F ? Float.floatToIntBits(this.m31) : 0);
|
||||
i = 31 * i + (this.m32 != 0.0F ? Float.floatToIntBits(this.m32) : 0);
|
||||
return 31 * i + (this.m33 != 0.0F ? Float.floatToIntBits(this.m33) : 0);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "Matrix4f:\n" +
|
||||
this.m00 + " " + this.m01 + " " + this.m02 + " " + this.m03 + "\n" +
|
||||
this.m10 + " " + this.m11 + " " + this.m12 + " " + this.m13 + "\n" +
|
||||
this.m20 + " " + this.m21 + " " + this.m22 + " " + this.m23 + "\n" +
|
||||
this.m30 + " " + this.m31 + " " + this.m32 + " " + this.m33 + "\n";
|
||||
}
|
||||
|
||||
|
||||
//=========//
|
||||
// methods //
|
||||
//=========//
|
||||
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 Matrix4f createJomlMatrix()
|
||||
{
|
||||
return new Matrix4f(
|
||||
this.m00, this.m10, this.m20, this.m30,
|
||||
this.m01, this.m11, this.m21, this.m31,
|
||||
this.m02, this.m12, this.m22, this.m32,
|
||||
this.m03, this.m13, this.m23, this.m33
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
private static int bufferIndex(int xIndex, int zIndex)
|
||||
{
|
||||
return (zIndex * 4) + xIndex;
|
||||
}
|
||||
|
||||
|
||||
public void setIdentity()
|
||||
{
|
||||
@@ -223,7 +341,7 @@ public class DhApiMat4f implements IDhApiCopyable
|
||||
}
|
||||
}
|
||||
|
||||
public void multiply(DhApiMat4f multMatrix)
|
||||
public void multiply(Mat4f multMatrix)
|
||||
{
|
||||
float f = this.m00 * multMatrix.m00 + this.m01 * multMatrix.m10 + this.m02 * multMatrix.m20 + this.m03 * multMatrix.m30;
|
||||
float f1 = this.m00 * multMatrix.m01 + this.m01 * multMatrix.m11 + this.m02 * multMatrix.m21 + this.m03 * multMatrix.m31;
|
||||
@@ -259,6 +377,13 @@ public class DhApiMat4f implements IDhApiCopyable
|
||||
this.m33 = f15;
|
||||
}
|
||||
|
||||
/* Quaternions aren't currently needed/implemented
|
||||
public void multiply(Quaternion p_226596_1_)
|
||||
{
|
||||
this.multiply(new Matrix4f(p_226596_1_));
|
||||
}
|
||||
*/
|
||||
|
||||
public void multiply(float scalar)
|
||||
{
|
||||
this.m00 *= scalar;
|
||||
@@ -279,6 +404,81 @@ public class DhApiMat4f implements IDhApiCopyable
|
||||
this.m33 *= scalar;
|
||||
}
|
||||
|
||||
public static Mat4f perspective(double fov, float widthHeightRatio, float nearClipPlane, float farClipPlane)
|
||||
{
|
||||
float f = (float) (1.0D / Math.tan(fov * ((float) Math.PI / 180F) / 2.0D));
|
||||
Mat4f matrix = new Mat4f();
|
||||
matrix.m00 = f / widthHeightRatio;
|
||||
matrix.m11 = f;
|
||||
matrix.m22 = (farClipPlane + nearClipPlane) / (nearClipPlane - farClipPlane);
|
||||
matrix.m32 = -1.0F;
|
||||
matrix.m23 = 2.0F * farClipPlane * nearClipPlane / (nearClipPlane - farClipPlane);
|
||||
return matrix;
|
||||
}
|
||||
|
||||
|
||||
/* not currently needed/implemented
|
||||
* Also the parameter names should be double checked as they may be incorrect
|
||||
public static Matrix4Float orthographic(float left, float right, float top, float bottom)
|
||||
{
|
||||
Matrix4Float matrix4f = new Matrix4Float();
|
||||
matrix4f.m00 = 2.0F / left;
|
||||
matrix4f.m11 = 2.0F / right;
|
||||
float f = bottom - top;
|
||||
matrix4f.m22 = -2.0F / f;
|
||||
matrix4f.m33 = 1.0F;
|
||||
matrix4f.m03 = -1.0F;
|
||||
matrix4f.m13 = -1.0F;
|
||||
matrix4f.m23 = -(bottom + top) / f;
|
||||
return matrix4f;
|
||||
}
|
||||
*/
|
||||
|
||||
/**
|
||||
* TODO: what kind of translation is this?
|
||||
* and how is this different from "multiplyTranslationMatrix"?
|
||||
* Answer: This is faster and direct (but only if this is pure translation matrix without rotate)
|
||||
*/
|
||||
public void translate(Vec3f vec)
|
||||
{
|
||||
this.m03 += vec.x;
|
||||
this.m13 += vec.y;
|
||||
this.m23 += vec.z;
|
||||
}
|
||||
|
||||
/** originally "translate" from Minecraft's MatrixStack */
|
||||
public void multiplyTranslationMatrix(double x, double y, double z)
|
||||
{
|
||||
multiply(createTranslateMatrix((float) x, (float) y, (float) z));
|
||||
}
|
||||
|
||||
public Mat4f copy()
|
||||
{
|
||||
return new Mat4f(this);
|
||||
}
|
||||
|
||||
public static Mat4f createScaleMatrix(float x, float y, float z)
|
||||
{
|
||||
Mat4f matrix = new Mat4f();
|
||||
matrix.m00 = x;
|
||||
matrix.m11 = y;
|
||||
matrix.m22 = z;
|
||||
matrix.m33 = 1.0F;
|
||||
return matrix;
|
||||
}
|
||||
|
||||
public static Mat4f createTranslateMatrix(float x, float y, float z)
|
||||
{
|
||||
Mat4f matrix = new Mat4f();
|
||||
matrix.m00 = 1.0F;
|
||||
matrix.m11 = 1.0F;
|
||||
matrix.m22 = 1.0F;
|
||||
matrix.m33 = 1.0F;
|
||||
matrix.m03 = x;
|
||||
matrix.m13 = y;
|
||||
matrix.m23 = z;
|
||||
return matrix;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -287,8 +487,6 @@ public class DhApiMat4f implements IDhApiCopyable
|
||||
// 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()
|
||||
{
|
||||
@@ -315,77 +513,113 @@ public class DhApiMat4f implements IDhApiCopyable
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// base overrides //
|
||||
//================//
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
public Vec3f asNonNormalizedLookForwardVector()
|
||||
{
|
||||
if (this == obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (obj != null && this.getClass() == obj.getClass())
|
||||
{
|
||||
DhApiMat4f otherMatrix = (DhApiMat4f) obj;
|
||||
return Float.compare(otherMatrix.m00, this.m00) == 0
|
||||
&& Float.compare(otherMatrix.m01, this.m01) == 0
|
||||
&& Float.compare(otherMatrix.m02, this.m02) == 0
|
||||
&& Float.compare(otherMatrix.m03, this.m03) == 0
|
||||
&& Float.compare(otherMatrix.m10, this.m10) == 0
|
||||
&& Float.compare(otherMatrix.m11, this.m11) == 0
|
||||
&& Float.compare(otherMatrix.m12, this.m12) == 0
|
||||
&& Float.compare(otherMatrix.m13, this.m13) == 0
|
||||
&& Float.compare(otherMatrix.m20, this.m20) == 0
|
||||
&& Float.compare(otherMatrix.m21, this.m21) == 0
|
||||
&& Float.compare(otherMatrix.m22, this.m22) == 0
|
||||
&& Float.compare(otherMatrix.m23, this.m23) == 0
|
||||
&& Float.compare(otherMatrix.m30, this.m30) == 0
|
||||
&& Float.compare(otherMatrix.m31, this.m31) == 0
|
||||
&& Float.compare(otherMatrix.m32, this.m32) == 0
|
||||
&& Float.compare(otherMatrix.m33, this.m33) == 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return new Vec3f(this.m02, this.m12, this.m22);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
//===============//
|
||||
// Forge methods //
|
||||
//===============//
|
||||
|
||||
public Mat4f(float[] values)
|
||||
{
|
||||
int i = this.m00 != 0.0F ? Float.floatToIntBits(this.m00) : 0;
|
||||
i = 31 * i + (this.m01 != 0.0F ? Float.floatToIntBits(this.m01) : 0);
|
||||
i = 31 * i + (this.m02 != 0.0F ? Float.floatToIntBits(this.m02) : 0);
|
||||
i = 31 * i + (this.m03 != 0.0F ? Float.floatToIntBits(this.m03) : 0);
|
||||
i = 31 * i + (this.m10 != 0.0F ? Float.floatToIntBits(this.m10) : 0);
|
||||
i = 31 * i + (this.m11 != 0.0F ? Float.floatToIntBits(this.m11) : 0);
|
||||
i = 31 * i + (this.m12 != 0.0F ? Float.floatToIntBits(this.m12) : 0);
|
||||
i = 31 * i + (this.m13 != 0.0F ? Float.floatToIntBits(this.m13) : 0);
|
||||
i = 31 * i + (this.m20 != 0.0F ? Float.floatToIntBits(this.m20) : 0);
|
||||
i = 31 * i + (this.m21 != 0.0F ? Float.floatToIntBits(this.m21) : 0);
|
||||
i = 31 * i + (this.m22 != 0.0F ? Float.floatToIntBits(this.m22) : 0);
|
||||
i = 31 * i + (this.m23 != 0.0F ? Float.floatToIntBits(this.m23) : 0);
|
||||
i = 31 * i + (this.m30 != 0.0F ? Float.floatToIntBits(this.m30) : 0);
|
||||
i = 31 * i + (this.m31 != 0.0F ? Float.floatToIntBits(this.m31) : 0);
|
||||
i = 31 * i + (this.m32 != 0.0F ? Float.floatToIntBits(this.m32) : 0);
|
||||
return 31 * i + (this.m33 != 0.0F ? Float.floatToIntBits(this.m33) : 0);
|
||||
m00 = values[0];
|
||||
m01 = values[1];
|
||||
m02 = values[2];
|
||||
m03 = values[3];
|
||||
m10 = values[4];
|
||||
m11 = values[5];
|
||||
m12 = values[6];
|
||||
m13 = values[7];
|
||||
m20 = values[8];
|
||||
m21 = values[9];
|
||||
m22 = values[10];
|
||||
m23 = values[11];
|
||||
m30 = values[12];
|
||||
m31 = values[13];
|
||||
m32 = values[14];
|
||||
m33 = values[15];
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
public Mat4f(FloatBuffer buffer)
|
||||
{
|
||||
return "Matrix4f:\n" +
|
||||
this.m00 + " " + this.m01 + " " + this.m02 + " " + this.m03 + "\n" +
|
||||
this.m10 + " " + this.m11 + " " + this.m12 + " " + this.m13 + "\n" +
|
||||
this.m20 + " " + this.m21 + " " + this.m22 + " " + this.m23 + "\n" +
|
||||
this.m30 + " " + this.m31 + " " + this.m32 + " " + this.m33 + "\n";
|
||||
this(buffer.array());
|
||||
}
|
||||
|
||||
@Override
|
||||
public DhApiMat4f copy() { return new DhApiMat4f(this); }
|
||||
public void set(Mat4f 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(Mat4f other)
|
||||
{
|
||||
m00 += other.m00;
|
||||
m01 += other.m01;
|
||||
m02 += other.m02;
|
||||
m03 += other.m03;
|
||||
m10 += other.m10;
|
||||
m11 += other.m11;
|
||||
m12 += other.m12;
|
||||
m13 += other.m13;
|
||||
m20 += other.m20;
|
||||
m21 += other.m21;
|
||||
m22 += other.m22;
|
||||
m23 += other.m23;
|
||||
m30 += other.m30;
|
||||
m31 += other.m31;
|
||||
m32 += other.m32;
|
||||
m33 += other.m33;
|
||||
}
|
||||
|
||||
public void multiplyBackward(Mat4f other)
|
||||
{
|
||||
Mat4f copy = other.copy();
|
||||
copy.multiply(this);
|
||||
this.set(copy);
|
||||
}
|
||||
|
||||
public void setTranslation(float x, float y, float z)
|
||||
{
|
||||
this.m00 = 1.0F;
|
||||
this.m11 = 1.0F;
|
||||
this.m22 = 1.0F;
|
||||
this.m33 = 1.0F;
|
||||
this.m03 = x;
|
||||
this.m13 = y;
|
||||
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)
|
||||
{
|
||||
//convert to matrix values, formula copied from a textbook / openGL specification.
|
||||
float matNearClip = -((farClip + nearClip) / (farClip - nearClip));
|
||||
float matFarClip = -((2 * farClip * nearClip) / (farClip - nearClip));
|
||||
//set new values for the clip planes.
|
||||
this.m22 = matNearClip;
|
||||
this.m23 = matFarClip;
|
||||
}
|
||||
|
||||
}
|
||||
+125
-14
@@ -17,9 +17,8 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.core.util.math;
|
||||
package com.seibel.distanthorizons.coreapi.util.math;
|
||||
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
|
||||
import com.seibel.distanthorizons.coreapi.util.MathUtil;
|
||||
|
||||
/**
|
||||
@@ -30,7 +29,7 @@ import com.seibel.distanthorizons.coreapi.util.MathUtil;
|
||||
* @author James Seibel
|
||||
* @version 11-18-2021
|
||||
*/
|
||||
public class Vec3d extends DhApiVec3d
|
||||
public class Vec3d
|
||||
{
|
||||
public static Vec3d XNeg = new Vec3d(-1.0F, 0.0F, 0.0F);
|
||||
public static Vec3d XPos = new Vec3d(1.0F, 0.0F, 0.0F);
|
||||
@@ -41,13 +40,16 @@ public class Vec3d extends DhApiVec3d
|
||||
|
||||
public static final Vec3d ZERO_VECTOR = new Vec3d(0.0D, 0.0D, 0.0D);
|
||||
|
||||
public double x;
|
||||
public double y;
|
||||
public double z;
|
||||
|
||||
|
||||
//==============//
|
||||
// constructors //
|
||||
//==============//
|
||||
|
||||
public Vec3d() { }
|
||||
public Vec3d()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Vec3d(double x, double y, double z)
|
||||
{
|
||||
@@ -56,11 +58,47 @@ public class Vec3d extends DhApiVec3d
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (obj != null && this.getClass() == obj.getClass())
|
||||
{
|
||||
Vec3d Vec3f = (Vec3d) obj;
|
||||
if (Double.compare(Vec3f.x, this.x) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (Double.compare(Vec3f.y, this.y) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Double.compare(Vec3f.z, this.z) == 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//=========//
|
||||
// methods //
|
||||
//=========//
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
long longVal = Double.doubleToLongBits(this.x);
|
||||
|
||||
int intVal = (int) (longVal ^ longVal >>> 32);
|
||||
longVal = Double.doubleToLongBits(this.y);
|
||||
intVal = 31 * intVal + (int) (longVal ^ longVal >>> 32);
|
||||
longVal = Double.doubleToLongBits(this.z);
|
||||
|
||||
return 31 * intVal + (int) (longVal ^ longVal >>> 32);
|
||||
}
|
||||
|
||||
public void mul(double scalar)
|
||||
{
|
||||
@@ -111,7 +149,10 @@ public class Vec3d extends DhApiVec3d
|
||||
this.z -= vector.z;
|
||||
}
|
||||
|
||||
public double dotProduct(Vec3d vector) { return this.x * vector.x + this.y * vector.y + this.z * vector.z; }
|
||||
public double dotProduct(Vec3d vector)
|
||||
{
|
||||
return this.x * vector.x + this.y * vector.y + this.z * vector.z;
|
||||
}
|
||||
|
||||
public Vec3d normalize()
|
||||
{
|
||||
@@ -132,10 +173,80 @@ public class Vec3d extends DhApiVec3d
|
||||
this.z = f * f4 - f1 * f3;
|
||||
}
|
||||
|
||||
public Vec3d copy() { return new Vec3d(this.x, this.y, this.z); }
|
||||
/* Matrix3f is not currently needed/implemented
|
||||
public void transform(Matrix3f p_229188_1_)
|
||||
{
|
||||
double f = this.x;
|
||||
double f1 = this.y;
|
||||
double f2 = this.z;
|
||||
this.x = p_229188_1_.m00 * f + p_229188_1_.m01 * f1 + p_229188_1_.m02 * f2;
|
||||
this.y = p_229188_1_.m10 * f + p_229188_1_.m11 * f1 + p_229188_1_.m12 * f2;
|
||||
this.z = p_229188_1_.m20 * f + p_229188_1_.m21 * f1 + p_229188_1_.m22 * f2;
|
||||
}
|
||||
*/
|
||||
|
||||
/* Quaternions are not currently needed/implemented
|
||||
public void transform(Quaternion p_214905_1_)
|
||||
{
|
||||
Quaternion quaternion = new Quaternion(p_214905_1_);
|
||||
quaternion.mul(new Quaternion(this.x(), this.y(), this.z(), 0.0F));
|
||||
Quaternion quaternion1 = new Quaternion(p_214905_1_);
|
||||
quaternion1.conj();
|
||||
quaternion.mul(quaternion1);
|
||||
this.set(quaternion.i(), quaternion.j(), quaternion.k());
|
||||
}
|
||||
*/
|
||||
|
||||
/* not currently needed
|
||||
* percent may actually be partial ticks (which is available when rendering)
|
||||
public void linearInterp(Vec3f resultingVector, double percent)
|
||||
{
|
||||
double f = 1.0F - percent;
|
||||
this.x = this.x * f + resultingVector.x * percent;
|
||||
this.y = this.y * f + resultingVector.y * percent;
|
||||
this.z = this.z * f + resultingVector.z * percent;
|
||||
}
|
||||
*/
|
||||
|
||||
/* Quaternions are not currently needed/implemented
|
||||
public Quaternion rotation(double p_229193_1_)
|
||||
{
|
||||
return new Quaternion(this, p_229193_1_, false);
|
||||
}
|
||||
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public Quaternion rotationDegrees(double p_229187_1_)
|
||||
{
|
||||
return new Quaternion(this, p_229187_1_, true);
|
||||
}
|
||||
*/
|
||||
|
||||
public Vec3d copy()
|
||||
{
|
||||
return new Vec3d(this.x, this.y, this.z);
|
||||
}
|
||||
|
||||
/* not currently needed/implemented
|
||||
public void map(double2doubleFunction p_229191_1_)
|
||||
{
|
||||
this.x = p_229191_1_.get(this.x);
|
||||
this.y = p_229191_1_.get(this.y);
|
||||
this.z = p_229191_1_.get(this.z);
|
||||
}
|
||||
*/
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "[" + this.x + ", " + this.y + ", " + this.z + "]";
|
||||
}
|
||||
|
||||
// Forge start
|
||||
public Vec3d(double[] values) { this.set(values); }
|
||||
public Vec3d(double[] values)
|
||||
{
|
||||
set(values);
|
||||
}
|
||||
|
||||
public void set(double[] values)
|
||||
{
|
||||
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2023 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.coreapi.util.math;
|
||||
|
||||
import com.seibel.distanthorizons.coreapi.util.MathUtil;
|
||||
|
||||
/**
|
||||
* A (almost) exact copy of Minecraft's 1.16.5
|
||||
* implementation of a 3 element float vector.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 11-11-2021
|
||||
*/
|
||||
public class Vec3f
|
||||
{
|
||||
public static Vec3f XNeg = new Vec3f(-1.0F, 0.0F, 0.0F);
|
||||
public static Vec3f XPos = new Vec3f(1.0F, 0.0F, 0.0F);
|
||||
public static Vec3f YNeg = new Vec3f(0.0F, -1.0F, 0.0F);
|
||||
public static Vec3f YPos = new Vec3f(0.0F, 1.0F, 0.0F);
|
||||
public static Vec3f ZNeg = new Vec3f(0.0F, 0.0F, -1.0F);
|
||||
public static Vec3f ZPos = new Vec3f(0.0F, 0.0F, 1.0F);
|
||||
|
||||
|
||||
public float x;
|
||||
public float y;
|
||||
public float z;
|
||||
|
||||
|
||||
|
||||
public Vec3f()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public Vec3f(float x, float y, float z)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
if (this == obj)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else if (obj != null && this.getClass() == obj.getClass())
|
||||
{
|
||||
Vec3f Vec3f = (Vec3f) obj;
|
||||
if (Float.compare(Vec3f.x, this.x) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (Float.compare(Vec3f.y, this.y) != 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Float.compare(Vec3f.z, this.z) == 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode()
|
||||
{
|
||||
int i = Float.floatToIntBits(this.x);
|
||||
i = 31 * i + Float.floatToIntBits(this.y);
|
||||
return 31 * i + Float.floatToIntBits(this.z);
|
||||
}
|
||||
|
||||
public void mul(float scalar)
|
||||
{
|
||||
this.x *= scalar;
|
||||
this.y *= scalar;
|
||||
this.z *= scalar;
|
||||
}
|
||||
|
||||
public void mul(float x, float y, float z)
|
||||
{
|
||||
this.x *= x;
|
||||
this.y *= y;
|
||||
this.z *= z;
|
||||
}
|
||||
|
||||
public void clamp(float min, float max)
|
||||
{
|
||||
this.x = MathUtil.clamp(min, this.x, max);
|
||||
this.y = MathUtil.clamp(min, this.y, max);
|
||||
this.z = MathUtil.clamp(min, this.z, max);
|
||||
}
|
||||
|
||||
public void set(float x, float y, float z)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
public void add(float x, float y, float z)
|
||||
{
|
||||
this.x += x;
|
||||
this.y += y;
|
||||
this.z += z;
|
||||
}
|
||||
|
||||
public void add(Vec3f vector)
|
||||
{
|
||||
this.x += vector.x;
|
||||
this.y += vector.y;
|
||||
this.z += vector.z;
|
||||
}
|
||||
|
||||
public void subtract(Vec3f vector)
|
||||
{
|
||||
this.x -= vector.x;
|
||||
this.y -= vector.y;
|
||||
this.z -= vector.z;
|
||||
}
|
||||
|
||||
public float dotProduct(Vec3f vector)
|
||||
{
|
||||
return this.x * vector.x + this.y * vector.y + this.z * vector.z;
|
||||
}
|
||||
|
||||
/** Returns true if normalization had to be done */
|
||||
public boolean normalize()
|
||||
{
|
||||
float squaredSum = this.x * this.x + this.y * this.y + this.z * this.z;
|
||||
if (squaredSum < 1.0E-5D)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
float f1 = MathUtil.fastInvSqrt(squaredSum);
|
||||
this.x *= f1;
|
||||
this.y *= f1;
|
||||
this.z *= f1;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
public void crossProduct(Vec3f vector)
|
||||
{
|
||||
float f = this.x;
|
||||
float f1 = this.y;
|
||||
float f2 = this.z;
|
||||
float f3 = vector.x;
|
||||
float f4 = vector.y;
|
||||
float f5 = vector.z;
|
||||
this.x = f1 * f5 - f2 * f4;
|
||||
this.y = f2 * f3 - f * f5;
|
||||
this.z = f * f4 - f1 * f3;
|
||||
}
|
||||
|
||||
/* Matrix3f is not currently needed/implemented
|
||||
public void transform(Matrix3f p_229188_1_)
|
||||
{
|
||||
float f = this.x;
|
||||
float f1 = this.y;
|
||||
float f2 = this.z;
|
||||
this.x = p_229188_1_.m00 * f + p_229188_1_.m01 * f1 + p_229188_1_.m02 * f2;
|
||||
this.y = p_229188_1_.m10 * f + p_229188_1_.m11 * f1 + p_229188_1_.m12 * f2;
|
||||
this.z = p_229188_1_.m20 * f + p_229188_1_.m21 * f1 + p_229188_1_.m22 * f2;
|
||||
}
|
||||
*/
|
||||
|
||||
/* Quaternions are not currently needed/implemented
|
||||
public void transform(Quaternion p_214905_1_)
|
||||
{
|
||||
Quaternion quaternion = new Quaternion(p_214905_1_);
|
||||
quaternion.mul(new Quaternion(this.x(), this.y(), this.z(), 0.0F));
|
||||
Quaternion quaternion1 = new Quaternion(p_214905_1_);
|
||||
quaternion1.conj();
|
||||
quaternion.mul(quaternion1);
|
||||
this.set(quaternion.i(), quaternion.j(), quaternion.k());
|
||||
}
|
||||
*/
|
||||
|
||||
/* not currently needed
|
||||
* percent may actually be partial ticks (which is available when rendering)
|
||||
public void linearInterp(Vec3f resultingVector, float percent)
|
||||
{
|
||||
float f = 1.0F - percent;
|
||||
this.x = this.x * f + resultingVector.x * percent;
|
||||
this.y = this.y * f + resultingVector.y * percent;
|
||||
this.z = this.z * f + resultingVector.z * percent;
|
||||
}
|
||||
*/
|
||||
|
||||
/* Quaternions are not currently needed/implemented
|
||||
public Quaternion rotation(float p_229193_1_)
|
||||
{
|
||||
return new Quaternion(this, p_229193_1_, false);
|
||||
}
|
||||
|
||||
|
||||
@OnlyIn(Dist.CLIENT)
|
||||
public Quaternion rotationDegrees(float p_229187_1_)
|
||||
{
|
||||
return new Quaternion(this, p_229187_1_, true);
|
||||
}
|
||||
*/
|
||||
|
||||
public Vec3f copy()
|
||||
{
|
||||
return new Vec3f(this.x, this.y, this.z);
|
||||
}
|
||||
|
||||
/* not currently needed/implemented
|
||||
public void map(Float2FloatFunction p_229191_1_)
|
||||
{
|
||||
this.x = p_229191_1_.get(this.x);
|
||||
this.y = p_229191_1_.get(this.y);
|
||||
this.z = p_229191_1_.get(this.z);
|
||||
}
|
||||
*/
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "[" + this.x + ", " + this.y + ", " + this.z + "]";
|
||||
}
|
||||
|
||||
// Forge start
|
||||
public Vec3f(float[] values)
|
||||
{
|
||||
set(values);
|
||||
}
|
||||
|
||||
public void set(float[] values)
|
||||
{
|
||||
this.x = values[0];
|
||||
this.y = values[1];
|
||||
this.z = values[2];
|
||||
}
|
||||
|
||||
}
|
||||
+1
-1
@@ -17,7 +17,7 @@
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.core.util.math;
|
||||
package com.seibel.distanthorizons.coreapi.util.math;
|
||||
|
||||
import com.seibel.distanthorizons.coreapi.util.MathUtil;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3i;
|
||||
@@ -20,7 +20,6 @@
|
||||
package com.seibel.distanthorizons.core;
|
||||
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericRenderObjectFactory;
|
||||
import com.seibel.distanthorizons.core.sql.DatabaseUpdater;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
@@ -97,7 +96,6 @@ public class Initializer
|
||||
DhApi.Delayed.terrainRepo = DhApiTerrainDataRepo.INSTANCE;
|
||||
DhApi.Delayed.worldProxy = DhApiWorldProxy.INSTANCE;
|
||||
DhApi.Delayed.renderProxy = DhApiRenderProxy.INSTANCE;
|
||||
DhApi.Delayed.customRenderObjectFactory = GenericRenderObjectFactory.INSTANCE;
|
||||
DhApi.Delayed.wrapperFactory = SingletonInjector.INSTANCE.get(IWrapperFactory.class);
|
||||
if (DhApi.Delayed.wrapperFactory == null)
|
||||
{
|
||||
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2023 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.core.api.external.methods.config.client;
|
||||
|
||||
import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue;
|
||||
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiGenericRenderingConfig;
|
||||
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiNoiseTextureConfig;
|
||||
import com.seibel.distanthorizons.api.objects.config.DhApiConfigValue;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
|
||||
public class DhApiGenericRenderingConfig implements IDhApiGenericRenderingConfig
|
||||
{
|
||||
public static DhApiGenericRenderingConfig INSTANCE = new DhApiGenericRenderingConfig();
|
||||
|
||||
private DhApiGenericRenderingConfig() { }
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public IDhApiConfigValue<Boolean> renderingEnabled()
|
||||
{ return new DhApiConfigValue<Boolean, Boolean>(Config.Client.Advanced.Graphics.GenericRendering.enableRendering); }
|
||||
@Override
|
||||
public IDhApiConfigValue<Boolean> beaconRenderingEnabled()
|
||||
{ return new DhApiConfigValue<Boolean, Boolean>(Config.Client.Advanced.Graphics.GenericRendering.enableBeaconRendering); }
|
||||
@Override
|
||||
public IDhApiConfigValue<Boolean> cloudRenderingEnabled()
|
||||
{ return new DhApiConfigValue<Boolean, Boolean>(Config.Client.Advanced.Graphics.GenericRendering.enableCloudRendering); }
|
||||
|
||||
}
|
||||
+4
-6
@@ -22,7 +22,10 @@ package com.seibel.distanthorizons.core.api.external.methods.config.client;
|
||||
import com.seibel.distanthorizons.api.enums.config.*;
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiTransparency;
|
||||
import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue;
|
||||
import com.seibel.distanthorizons.api.interfaces.config.client.*;
|
||||
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiAmbientOcclusionConfig;
|
||||
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiFogConfig;
|
||||
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiGraphicsConfig;
|
||||
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiNoiseTextureConfig;
|
||||
import com.seibel.distanthorizons.api.objects.config.DhApiConfigValue;
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiRendererMode;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
@@ -39,14 +42,9 @@ public class DhApiGraphicsConfig implements IDhApiGraphicsConfig
|
||||
// inner layers //
|
||||
//==============//
|
||||
|
||||
@Override
|
||||
public IDhApiFogConfig fog() { return DhApiFogConfig.INSTANCE; }
|
||||
@Override
|
||||
public IDhApiAmbientOcclusionConfig ambientOcclusion() { return DhApiAmbientOcclusionConfig.INSTANCE; }
|
||||
@Override
|
||||
public IDhApiNoiseTextureConfig noiseTexture() { return DhApiNoiseTextureConfig.INSTANCE; }
|
||||
@Override
|
||||
public IDhApiGenericRenderingConfig genericRendering() { return DhApiGenericRenderingConfig.INSTANCE; }
|
||||
|
||||
|
||||
|
||||
|
||||
-87
@@ -1,87 +0,0 @@
|
||||
package com.seibel.distanthorizons.core.api.external.methods.data;
|
||||
|
||||
import com.seibel.distanthorizons.api.interfaces.data.IDhApiTerrainDataCache;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.longs.LongSet;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.ref.SoftReference;
|
||||
|
||||
public class DhApiTerrainDataCache implements IDhApiTerrainDataCache
|
||||
{
|
||||
private final Object modificationLock = new Object();
|
||||
private Long2ReferenceOpenHashMap<SoftReference<FullDataSourceV2>> posToFullDataRef = new Long2ReferenceOpenHashMap<>();
|
||||
|
||||
private static final Logger LOGGER = LogManager.getLogger(DhApiTerrainDataCache.class.getSimpleName());
|
||||
|
||||
|
||||
|
||||
//==================//
|
||||
// internal methods //
|
||||
//==================//
|
||||
|
||||
public void add(long pos, FullDataSourceV2 dataSource)
|
||||
{
|
||||
synchronized (this.modificationLock)
|
||||
{
|
||||
this.posToFullDataRef.put(pos, new SoftReference<>(dataSource));
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public FullDataSourceV2 get(long pos)
|
||||
{
|
||||
synchronized (this.modificationLock)
|
||||
{
|
||||
SoftReference<FullDataSourceV2> ref = this.posToFullDataRef.get(pos);
|
||||
if (ref != null)
|
||||
{
|
||||
return ref.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// API methods //
|
||||
//=============//
|
||||
|
||||
@Override
|
||||
public void clear()
|
||||
{
|
||||
synchronized (this.modificationLock)
|
||||
{
|
||||
LongSet keySet = this.posToFullDataRef.keySet();
|
||||
for (long pos : keySet)
|
||||
{
|
||||
SoftReference<FullDataSourceV2> dataRef = this.posToFullDataRef.remove(pos);
|
||||
if (dataRef != null)
|
||||
{
|
||||
FullDataSourceV2 dataSource = dataRef.get();
|
||||
if (dataSource != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
dataSource.close();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.warn("Unable to close data source, error: [" + e.getMessage() + "].", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
+88
-141
@@ -19,7 +19,6 @@
|
||||
|
||||
package com.seibel.distanthorizons.core.api.external.methods.data;
|
||||
|
||||
import com.seibel.distanthorizons.api.interfaces.data.IDhApiTerrainDataCache;
|
||||
import com.seibel.distanthorizons.api.interfaces.world.IDhApiLevelWrapper;
|
||||
import com.seibel.distanthorizons.api.objects.DhApiResult;
|
||||
import com.seibel.distanthorizons.api.objects.data.DhApiRaycastResult;
|
||||
@@ -36,7 +35,6 @@ import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.util.FullDataPointUtil;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.RayCastUtil;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||
import com.seibel.distanthorizons.core.world.AbstractDhWorld;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||
@@ -45,12 +43,12 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRen
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.util.BitShiftUtil;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3i;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Vec3f;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Vec3i;
|
||||
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
@@ -58,6 +56,9 @@ import java.util.concurrent.ExecutionException;
|
||||
|
||||
/**
|
||||
* Allows interfacing with the terrain data Distant Horizons has stored.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 2022-11-19
|
||||
*/
|
||||
public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
|
||||
{
|
||||
@@ -67,15 +68,12 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
|
||||
|
||||
// debugging values
|
||||
private static volatile boolean debugThreadRunning = false;
|
||||
private static DhApiTerrainDataCache debugDataCache = new DhApiTerrainDataCache();
|
||||
private static String currentDebugBiomeName = "";
|
||||
private static int currentDebugBlockColorInt = -1;
|
||||
private static DhApiVec3i currentDebugVec3i = new Vec3i();
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
private DhApiTerrainDataRepo()
|
||||
{
|
||||
|
||||
@@ -88,32 +86,41 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
|
||||
//================//
|
||||
|
||||
@Override
|
||||
public DhApiResult<DhApiTerrainDataPoint> getSingleDataPointAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosY, int blockPosZ, @Nullable IDhApiTerrainDataCache dataCache)
|
||||
{ return getTerrainDataAtBlockYPos(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), blockPosY, dataCache); }
|
||||
public DhApiResult<DhApiTerrainDataPoint> getSingleDataPointAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosY, int blockPosZ)
|
||||
{
|
||||
return getTerrainDataAtBlockYPos(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), blockPosY);
|
||||
}
|
||||
@Override
|
||||
public DhApiResult<DhApiTerrainDataPoint[]> getColumnDataAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosZ, @Nullable IDhApiTerrainDataCache dataCache)
|
||||
{ return getTerrainDataColumnArray(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), null, dataCache); }
|
||||
public DhApiResult<DhApiTerrainDataPoint[]> getColumnDataAtBlockPos(IDhApiLevelWrapper levelWrapper, int blockPosX, int blockPosZ)
|
||||
{
|
||||
return getTerrainDataColumnArray(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtChunkPos(IDhApiLevelWrapper levelWrapper, int chunkPosX, int chunkPosZ, @Nullable IDhApiTerrainDataCache dataCache)
|
||||
{ return getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, new DhLodPos(LodUtil.CHUNK_DETAIL_LEVEL, chunkPosX, chunkPosZ), dataCache); }
|
||||
public DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtChunkPos(IDhApiLevelWrapper levelWrapper, int chunkPosX, int chunkPosZ)
|
||||
{
|
||||
return getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, new DhLodPos(LodUtil.CHUNK_DETAIL_LEVEL, chunkPosX, chunkPosZ));
|
||||
}
|
||||
|
||||
@Override
|
||||
public DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtRegionPos(IDhApiLevelWrapper levelWrapper, int regionPosX, int regionPosZ, @Nullable IDhApiTerrainDataCache dataCache)
|
||||
{ return getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, new DhLodPos(LodUtil.REGION_DETAIL_LEVEL, regionPosX, regionPosZ), dataCache); }
|
||||
public DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtRegionPos(IDhApiLevelWrapper levelWrapper, int regionPosX, int regionPosZ)
|
||||
{
|
||||
return getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, new DhLodPos(LodUtil.REGION_DETAIL_LEVEL, regionPosX, regionPosZ));
|
||||
}
|
||||
|
||||
@Override
|
||||
public DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtDetailLevelAndPos(IDhApiLevelWrapper levelWrapper, byte detailLevel, int posX, int posZ, @Nullable IDhApiTerrainDataCache dataCache)
|
||||
{ return getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, new DhLodPos(detailLevel, posX, posZ), dataCache); }
|
||||
|
||||
public DhApiResult<DhApiTerrainDataPoint[][][]> getAllTerrainDataAtDetailLevelAndPos(IDhApiLevelWrapper levelWrapper, byte detailLevel, int posX, int posZ)
|
||||
{
|
||||
return getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, new DhLodPos(detailLevel, posX, posZ));
|
||||
}
|
||||
|
||||
|
||||
// private getters //
|
||||
|
||||
/** Returns a single API terrain datapoint that contains the given Y block position */
|
||||
private static DhApiResult<DhApiTerrainDataPoint> getTerrainDataAtBlockYPos(IDhApiLevelWrapper levelWrapper, DhLodPos requestedColumnPos, Integer blockYPos, @Nullable IDhApiTerrainDataCache dataCache)
|
||||
private static DhApiResult<DhApiTerrainDataPoint> getTerrainDataAtBlockYPos(IDhApiLevelWrapper levelWrapper, DhLodPos requestedColumnPos, Integer blockYPos)
|
||||
{
|
||||
DhApiResult<DhApiTerrainDataPoint[]> result = getTerrainDataColumnArray(levelWrapper, requestedColumnPos, blockYPos, dataCache);
|
||||
DhApiResult<DhApiTerrainDataPoint[]> result = getTerrainDataColumnArray(levelWrapper, requestedColumnPos, blockYPos);
|
||||
if (result.success && result.payload.length > 0)
|
||||
{
|
||||
return DhApiResult.createSuccess(result.message, result.payload[0]);
|
||||
@@ -133,9 +140,7 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
|
||||
*
|
||||
* will stop and return the in progress data if any errors are encountered.
|
||||
*/
|
||||
private static DhApiResult<DhApiTerrainDataPoint[][][]> getTerrainDataOverAreaForPositionDetailLevel(
|
||||
IDhApiLevelWrapper levelWrapper, DhLodPos requestedAreaPos,
|
||||
@Nullable IDhApiTerrainDataCache dataCache)
|
||||
private static DhApiResult<DhApiTerrainDataPoint[][][]> getTerrainDataOverAreaForPositionDetailLevel(IDhApiLevelWrapper levelWrapper, DhLodPos requestedAreaPos)
|
||||
{
|
||||
DhLodPos startingBlockPos = requestedAreaPos.getCornerLodPos(LodUtil.BLOCK_DETAIL_LEVEL);
|
||||
int widthOfAreaInBlocks = BitShiftUtil.powerOfTwo(requestedAreaPos.detailLevel);
|
||||
@@ -149,7 +154,7 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
|
||||
for (int z = 0; z < widthOfAreaInBlocks; z++)
|
||||
{
|
||||
DhLodPos blockColumnPos = new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, startingBlockPos.x + x, startingBlockPos.z + z);
|
||||
DhApiResult<DhApiTerrainDataPoint[]> result = getTerrainDataColumnArray(levelWrapper, blockColumnPos, null, dataCache);
|
||||
DhApiResult<DhApiTerrainDataPoint[]> result = getTerrainDataColumnArray(levelWrapper, blockColumnPos, null);
|
||||
if (result.success)
|
||||
{
|
||||
returnArray[x][z] = result.payload;
|
||||
@@ -172,15 +177,8 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
|
||||
* If the ApiResult is successful there will be an array of data. <br>
|
||||
* The returned array will be empty if no data could be retrieved.
|
||||
*/
|
||||
private static DhApiResult<DhApiTerrainDataPoint[]> getTerrainDataColumnArray(
|
||||
IDhApiLevelWrapper levelWrapper,
|
||||
DhLodPos requestedColumnPos, Integer nullableBlockYPos,
|
||||
@Nullable IDhApiTerrainDataCache apiDataCache)
|
||||
private static DhApiResult<DhApiTerrainDataPoint[]> getTerrainDataColumnArray(IDhApiLevelWrapper levelWrapper, DhLodPos requestedColumnPos, Integer nullableBlockYPos)
|
||||
{
|
||||
//============//
|
||||
// validation //
|
||||
//============//
|
||||
|
||||
AbstractDhWorld currentWorld = SharedApi.getAbstractDhWorld();
|
||||
if (currentWorld == null)
|
||||
{
|
||||
@@ -196,15 +194,6 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
|
||||
ILevelWrapper coreLevelWrapper = (ILevelWrapper) levelWrapper;
|
||||
|
||||
|
||||
if (!(apiDataCache instanceof DhApiTerrainDataCache))
|
||||
{
|
||||
// custom level wrappers aren't supported,
|
||||
// the API user must get a level wrapper from our code somewhere
|
||||
return DhApiResult.createFail("Unsupported [" + IDhApiTerrainDataCache.class.getSimpleName() + "] implementation, only the core class [" + DhApiTerrainDataCache.class.getSimpleName() + "] is a valid parameter.");
|
||||
}
|
||||
DhApiTerrainDataCache dataCache = (DhApiTerrainDataCache) apiDataCache;
|
||||
|
||||
|
||||
IDhLevel level = currentWorld.getLevel(coreLevelWrapper);
|
||||
if (level == null)
|
||||
{
|
||||
@@ -220,96 +209,70 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
|
||||
DhLodPos relativePos = requestedColumnPos.getDhSectionRelativePositionForDetailLevel();
|
||||
|
||||
|
||||
|
||||
//=====================//
|
||||
// get the data source //
|
||||
//=====================//
|
||||
|
||||
try
|
||||
{
|
||||
FullDataSourceV2 dataSource = null;
|
||||
|
||||
// try using the cached data if possible
|
||||
if (dataCache != null)
|
||||
{
|
||||
dataSource = dataCache.get(sectionPos);
|
||||
}
|
||||
|
||||
// attempt to get/generate the data source for this section
|
||||
FullDataSourceV2 dataSource = level.getFullDataProvider().getAsync(sectionPos).get();
|
||||
if (dataSource == null)
|
||||
{
|
||||
// attempt to get/generate the data source for this section
|
||||
dataSource = level.getFullDataProvider().getAsync(sectionPos).get();
|
||||
if (dataSource == null)
|
||||
{
|
||||
return DhApiResult.createFail("Unable to find/generate any data at the " + DhSectionPos.class.getSimpleName() + " [" + DhSectionPos.toString(sectionPos) + "].");
|
||||
}
|
||||
dataCache.add(sectionPos, dataSource);
|
||||
return DhApiResult.createFail("Unable to find/generate any data at the " + DhSectionPos.class.getSimpleName() + " [" + DhSectionPos.toString(sectionPos) + "].");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===============================//
|
||||
// get LOD data from data source //
|
||||
//===============================//
|
||||
|
||||
FullDataPointIdMap mapping = dataSource.mapping;
|
||||
LongArrayList dataColumn = dataSource.get(relativePos.x, relativePos.z);
|
||||
if (dataColumn != null)
|
||||
else
|
||||
{
|
||||
int dataColumnIndexCount = dataColumn.size();
|
||||
DhApiTerrainDataPoint[] returnArray = new DhApiTerrainDataPoint[dataColumnIndexCount];
|
||||
long dataPoint;
|
||||
|
||||
boolean getSpecificYCoordinate = nullableBlockYPos != null;
|
||||
int levelMinimumHeight = levelWrapper.getMinHeight();
|
||||
|
||||
|
||||
// search for a datapoint that contains the block y position
|
||||
for (int i = 0; i < dataColumnIndexCount; i++)
|
||||
// attempt to get the LOD data from the data source
|
||||
FullDataPointIdMap mapping = dataSource.mapping;
|
||||
LongArrayList dataColumn = dataSource.get(relativePos.x, relativePos.z);
|
||||
if (dataColumn != null)
|
||||
{
|
||||
dataPoint = dataColumn.getLong(i);
|
||||
int dataColumnIndexCount = dataColumn.size();
|
||||
DhApiTerrainDataPoint[] returnArray = new DhApiTerrainDataPoint[dataColumnIndexCount];
|
||||
long dataPoint;
|
||||
|
||||
if (!getSpecificYCoordinate)
|
||||
boolean getSpecificYCoordinate = nullableBlockYPos != null;
|
||||
int levelMinimumHeight = levelWrapper.getMinHeight();
|
||||
|
||||
|
||||
// search for a datapoint that contains the block y position
|
||||
for (int i = 0; i < dataColumnIndexCount; i++)
|
||||
{
|
||||
// if we aren't look for a specific datapoint, add each datapoint to the return array
|
||||
returnArray[i] = generateApiDatapoint(levelWrapper, mapping, requestedDetailLevel, dataPoint);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we are looking for a specific datapoint,
|
||||
// don't look at null ones
|
||||
if (dataPoint != 0)
|
||||
dataPoint = dataColumn.getLong(i);
|
||||
|
||||
if (!getSpecificYCoordinate)
|
||||
{
|
||||
int requestedY = nullableBlockYPos;
|
||||
int bottomY = FullDataPointUtil.getBottomY(dataPoint) + levelMinimumHeight;
|
||||
int height = FullDataPointUtil.getHeight(dataPoint);
|
||||
int topY = bottomY + height;
|
||||
|
||||
// does this datapoint contain the requested Y position?
|
||||
if (bottomY <= requestedY && requestedY < topY) // blockPositions start from the bottom of the block, thus "<=" for bottomY, just "<" for topY
|
||||
// if we aren't look for a specific datapoint, add each datapoint to the return array
|
||||
returnArray[i] = generateApiDatapoint(levelWrapper, mapping, requestedDetailLevel, dataPoint);
|
||||
}
|
||||
else
|
||||
{
|
||||
// we are looking for a specific datapoint,
|
||||
// don't look at null ones
|
||||
if (dataPoint != 0)
|
||||
{
|
||||
// this datapoint contains the requested block position, return it
|
||||
DhApiTerrainDataPoint apiTerrainData = generateApiDatapoint(levelWrapper, mapping, requestedDetailLevel, dataPoint);
|
||||
return DhApiResult.createSuccess(new DhApiTerrainDataPoint[]{apiTerrainData});
|
||||
int requestedY = nullableBlockYPos;
|
||||
int bottomY = FullDataPointUtil.getBottomY(dataPoint) + levelMinimumHeight;
|
||||
int height = FullDataPointUtil.getHeight(dataPoint);
|
||||
int topY = bottomY + height;
|
||||
|
||||
// does this datapoint contain the requested Y position?
|
||||
if (bottomY <= requestedY && requestedY < topY) // blockPositions start from the bottom of the block, thus "<=" for bottomY, just "<" for topY
|
||||
{
|
||||
// this datapoint contains the requested block position, return it
|
||||
DhApiTerrainDataPoint apiTerrainData = generateApiDatapoint(levelWrapper, mapping, requestedDetailLevel, dataPoint);
|
||||
return DhApiResult.createSuccess(new DhApiTerrainDataPoint[]{apiTerrainData});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// return all collected data
|
||||
return DhApiResult.createSuccess(returnArray);
|
||||
}
|
||||
|
||||
// return all collected data
|
||||
return DhApiResult.createSuccess(returnArray);
|
||||
// the requested data wasn't present in this column (and/or the column wasn't able to be accessed/generated)
|
||||
return DhApiResult.createSuccess(new DhApiTerrainDataPoint[0]);
|
||||
}
|
||||
|
||||
// the requested data wasn't present in this column (and/or the column wasn't able to be accessed/generated)
|
||||
return DhApiResult.createSuccess(new DhApiTerrainDataPoint[0]);
|
||||
}
|
||||
catch (InterruptedException | ExecutionException e)
|
||||
{
|
||||
// shouldn't normally happen, but just in case
|
||||
LOGGER.error("getTerrainDataColumnArray operation canceled. Error: [" + e.getMessage() + "]", e);
|
||||
return DhApiResult.createFail("Operation cancled before it could complete: [" + e.getMessage() + "].");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// shouldn't normally happen, but just in case
|
||||
LOGGER.error("Unexpected exception in getTerrainDataColumnArray. Error: [" + e.getMessage() + "]", e);
|
||||
@@ -343,11 +306,9 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
|
||||
IDhApiLevelWrapper levelWrapper,
|
||||
double rayOriginX, double rayOriginY, double rayOriginZ,
|
||||
float rayDirectionX, float rayDirectionY, float rayDirectionZ,
|
||||
int maxRayBlockLength,
|
||||
@Nullable
|
||||
IDhApiTerrainDataCache dataCache)
|
||||
int maxRayBlockLength)
|
||||
{
|
||||
return this.raycastLodData(levelWrapper, new Vec3d(rayOriginX, rayOriginY, rayOriginZ), new Vec3f(rayDirectionX, rayDirectionY, rayDirectionZ), maxRayBlockLength, dataCache);
|
||||
return this.raycastLodData(levelWrapper, new Vec3d(rayOriginX, rayOriginY, rayOriginZ), new Vec3f(rayDirectionX, rayDirectionY, rayDirectionZ), maxRayBlockLength);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -356,17 +317,12 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
|
||||
* Works by walking through the world and attempting to get the LOD <br>
|
||||
* data present at each step.
|
||||
*/
|
||||
private DhApiResult<DhApiRaycastResult> raycastLodData(
|
||||
IDhApiLevelWrapper levelWrapper,
|
||||
Vec3d rayOrigin, Vec3f rayDirection,
|
||||
int maxRayBlockLength,
|
||||
@Nullable
|
||||
IDhApiTerrainDataCache dataCache)
|
||||
private DhApiResult<DhApiRaycastResult> raycastLodData(IDhApiLevelWrapper levelWrapper, Vec3d rayOrigin, Vec3f rayDirection, int maxRayBlockLength)
|
||||
{
|
||||
rayDirection.normalize();
|
||||
|
||||
int minBlockHeight = levelWrapper.getMinHeight();
|
||||
int maxBlockHeight = levelWrapper.getMaxHeight();
|
||||
int maxBlockHeight = levelWrapper.getHeight();
|
||||
|
||||
|
||||
|
||||
@@ -390,7 +346,7 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
|
||||
for (Vec3i columnPos : columnPositions)
|
||||
{
|
||||
// check each column
|
||||
DhApiResult<DhApiTerrainDataPoint[]> result = this.getColumnDataAtBlockPos(levelWrapper, columnPos.x, columnPos.z, dataCache);
|
||||
DhApiResult<DhApiTerrainDataPoint[]> result = this.getColumnDataAtBlockPos(levelWrapper, columnPos.x, columnPos.z);
|
||||
if (!result.success)
|
||||
{
|
||||
// if there was an error, stop and return it
|
||||
@@ -458,7 +414,7 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
|
||||
*/
|
||||
private static ArrayList<Vec3i> getIntersectingColumnsAtPosition(Vec3i rayEndingPos, Vec3f rayDirection)
|
||||
{
|
||||
ArrayList<Vec3i> returnList = new ArrayList<>(9);
|
||||
ArrayList<Vec3i> returnList = new ArrayList<Vec3i>(9);
|
||||
|
||||
for (int x = -1; x <= 1; x++)
|
||||
{
|
||||
@@ -513,15 +469,6 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// API helpers //
|
||||
//=============//
|
||||
|
||||
@Override
|
||||
public IDhApiTerrainDataCache getSoftCache() { return new DhApiTerrainDataCache(); }
|
||||
|
||||
|
||||
|
||||
//===============//
|
||||
// debug methods //
|
||||
//===============//
|
||||
@@ -538,15 +485,15 @@ public class DhApiTerrainDataRepo implements IDhApiTerrainDataRepo
|
||||
Thread thread = new Thread(() -> {
|
||||
try
|
||||
{
|
||||
DhApiResult<DhApiTerrainDataPoint> single = getTerrainDataAtBlockYPos(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), blockPosY, debugDataCache);
|
||||
DhApiResult<DhApiTerrainDataPoint[]> column = getTerrainDataColumnArray(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), null, debugDataCache);
|
||||
DhApiResult<DhApiTerrainDataPoint> single = getTerrainDataAtBlockYPos(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), blockPosY);
|
||||
DhApiResult<DhApiTerrainDataPoint[]> column = getTerrainDataColumnArray(levelWrapper, new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ), null);
|
||||
|
||||
DhLodPos chunkPos = new DhLodPos(LodUtil.BLOCK_DETAIL_LEVEL, blockPosX, blockPosZ).convertToDetailLevel(LodUtil.CHUNK_DETAIL_LEVEL);
|
||||
DhApiResult<DhApiTerrainDataPoint[][][]> area = getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, chunkPos, debugDataCache);
|
||||
DhApiResult<DhApiTerrainDataPoint[][][]> area = getTerrainDataOverAreaForPositionDetailLevel(levelWrapper, chunkPos);
|
||||
|
||||
|
||||
IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
DhApiResult<DhApiRaycastResult> rayCast = INSTANCE.raycastLodData(levelWrapper, MC_RENDER.getCameraExactPosition(), MC_RENDER.getLookAtVector(), 1000, debugDataCache);
|
||||
DhApiResult<DhApiRaycastResult> rayCast = INSTANCE.raycastLodData(levelWrapper, MC_RENDER.getCameraExactPosition(), MC_RENDER.getLookAtVector(), 1000);
|
||||
if (rayCast.payload != null && !rayCast.payload.pos.equals(currentDebugVec3i))
|
||||
{
|
||||
currentDebugVec3i = rayCast.payload.pos;
|
||||
|
||||
@@ -23,12 +23,6 @@ import com.seibel.distanthorizons.api.DhApi;
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiRenderPass;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.*;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
|
||||
import com.seibel.distanthorizons.core.file.structure.ClientOnlySaveStructure;
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.render.DhApiRenderProxy;
|
||||
import com.seibel.distanthorizons.core.util.objects.Pair;
|
||||
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
|
||||
import com.seibel.distanthorizons.core.level.IDhClientLevel;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.network.messages.NetworkMessage;
|
||||
import com.seibel.distanthorizons.core.network.session.Session;
|
||||
@@ -36,14 +30,17 @@ import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiDebugRendering;
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiRendererMode;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.level.IDhClientLevel;
|
||||
import com.seibel.distanthorizons.core.level.IServerKeyedClientLevel;
|
||||
import com.seibel.distanthorizons.core.logging.ConfigBasedLogger;
|
||||
import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger;
|
||||
import com.seibel.distanthorizons.core.logging.SpamReducedLogger;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.render.DhApiRenderProxy;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
||||
import com.seibel.distanthorizons.core.render.renderer.TestRenderer;
|
||||
import com.seibel.distanthorizons.core.util.RenderUtil;
|
||||
import com.seibel.distanthorizons.core.util.objects.Pair;
|
||||
import com.seibel.distanthorizons.core.world.AbstractDhWorld;
|
||||
import com.seibel.distanthorizons.core.world.DhClientServerWorld;
|
||||
import com.seibel.distanthorizons.core.world.DhClientWorld;
|
||||
@@ -52,12 +49,13 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Queue;
|
||||
@@ -126,28 +124,9 @@ public class ClientApi
|
||||
public synchronized void onClientOnlyConnected()
|
||||
{
|
||||
// only continue if the client is connected to a different server
|
||||
boolean connectedToServer = MC.clientConnectedToDedicatedServer();
|
||||
boolean connectedToReplay = MC.connectedToReplay();
|
||||
if (connectedToServer || connectedToReplay)
|
||||
if (MC.clientConnectedToDedicatedServer())
|
||||
{
|
||||
if (connectedToServer)
|
||||
{
|
||||
LOGGER.info("Client on ClientOnly mode connecting.");
|
||||
}
|
||||
else
|
||||
{
|
||||
LOGGER.info("Replay on ClientServer mode connecting.");
|
||||
|
||||
if (Config.Client.Advanced.Logging.showReplayWarningOnStartup.get())
|
||||
{
|
||||
MC.sendChatMessage("\u00A76" + "Distant Horizons: Replay detected." + "\u00A7r"); // gold color
|
||||
MC.sendChatMessage("DH may behave strangely or have missing functionality.");
|
||||
MC.sendChatMessage("In order to use pre-generated LODs, put your DH database(s) in:");
|
||||
MC.sendChatMessage("\u00A77"+".Minecraft" + File.separator + ClientOnlySaveStructure.SERVER_DATA_FOLDER_NAME + File.separator + ClientOnlySaveStructure.REPLAY_SERVER_FOLDER_NAME + File.separator + "DIMENSION_NAME"+"\u00A7r"); // light gray color
|
||||
MC.sendChatMessage("This can be disabled in DH's config under Advanced -> Logging.");
|
||||
MC.sendChatMessage("");
|
||||
}
|
||||
}
|
||||
LOGGER.info("Client on ClientOnly mode connecting.");
|
||||
|
||||
// firing after clientLevelLoadEvent
|
||||
// TODO if level has prepped to load it should fire level load event
|
||||
@@ -468,7 +447,7 @@ public class ClientApi
|
||||
|
||||
if (!DhApi.Delayed.renderProxy.getDeferTransparentRendering())
|
||||
{
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterRenderEvent.class, null);
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterRenderEvent.class, renderEventParam);
|
||||
}
|
||||
}
|
||||
else if (Config.Client.Advanced.Debugging.rendererMode.get() == EDhApiRendererMode.DEBUG)
|
||||
@@ -489,7 +468,7 @@ public class ClientApi
|
||||
|
||||
if (DhApi.Delayed.renderProxy.getDeferTransparentRendering())
|
||||
{
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterRenderEvent.class, null);
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiAfterRenderEvent.class, renderEventParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -500,7 +479,6 @@ public class ClientApi
|
||||
|
||||
MC.sendChatMessage("\u00A74\u00A7l\u00A7uERROR: Distant Horizons renderer has encountered an exception!");
|
||||
MC.sendChatMessage("\u00A74Renderer is now disabled to prevent further issues.");
|
||||
MC.sendChatMessage("\u00A74Please restart your game to re-enable Distant Horizons' LOD rendering.");
|
||||
MC.sendChatMessage("\u00A74Exception detail: " + e);
|
||||
}
|
||||
finally
|
||||
|
||||
@@ -138,7 +138,7 @@ public class ServerApi
|
||||
//=======================//
|
||||
|
||||
public void serverChunkLoadEvent(IChunkWrapper chunkWrapper, ILevelWrapper level) { SharedApi.INSTANCE.applyChunkUpdate(chunkWrapper, level, false); }
|
||||
public void serverChunkSaveEvent(IChunkWrapper chunkWrapper, ILevelWrapper level) { SharedApi.INSTANCE.applyChunkUpdate(chunkWrapper, level, true); }
|
||||
public void serverChunkSaveEvent(IChunkWrapper chunkWrapper, ILevelWrapper level) { SharedApi.INSTANCE.applyChunkUpdate(chunkWrapper, level, false); }
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -29,8 +29,7 @@ import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
||||
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
|
||||
import com.seibel.distanthorizons.core.sql.repo.AbstractDhRepo;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.TimerUtil;
|
||||
import com.seibel.distanthorizons.core.util.objects.Pair;
|
||||
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
|
||||
@@ -57,7 +56,7 @@ public class SharedApi
|
||||
private static final Set<DhChunkPos> UPDATING_CHUNK_POS_SET = ConcurrentHashMap.newKeySet();
|
||||
/** how many chunks can be queued for updating per thread, used to prevent updates from infinitely pilling up if the user flys around extremely fast */
|
||||
private static final int MAX_UPDATING_CHUNK_COUNT_PER_THREAD = 500;
|
||||
private static final int MIN_MS_BETWEEN_OVERLOADED_LOG_MESSAGE = 30_000;
|
||||
private static final int MIN_MS_BETWEEN_OVERLOADED_LOG_MESSAGE = 5_000;
|
||||
|
||||
private static final Timer CHUNK_UPDATE_TIMER = TimerUtil.CreateTimer("ChunkUpdateTimer");
|
||||
|
||||
@@ -102,9 +101,7 @@ public class SharedApi
|
||||
{
|
||||
DebugRenderer.clearRenderables();
|
||||
MC_RENDER.clearTargetFrameBuffer();
|
||||
// shouldn't be necessary, but if we missed closing one of the connections this should make sure they're all closed
|
||||
AbstractDhRepo.closeAllConnections();
|
||||
// needs to be closed on world shutdown to clear out un-processed chunks
|
||||
// needs to be closed on world shutdown to clear out un-processed chunks
|
||||
UPDATING_CHUNK_POS_SET.clear();
|
||||
}
|
||||
|
||||
@@ -141,8 +138,7 @@ public class SharedApi
|
||||
* Used to prevent getting a full chunk from MC if it isn't necessary. <br>
|
||||
* This is important since asking MC for a chunk is slow and may block the render thread.
|
||||
*/
|
||||
public static boolean isChunkAtBlockPosAlreadyUpdating(int blockPosX, int blockPosZ)
|
||||
{ return UPDATING_CHUNK_POS_SET.contains(new DhChunkPos(new DhBlockPos2D(blockPosX, blockPosZ))); }
|
||||
public static boolean isChunkAtBlockPosAlreadyUpdating(int blockPosX, int blockPosZ) { return UPDATING_CHUNK_POS_SET.contains(new DhChunkPos(new DhBlockPos2D(blockPosX, blockPosZ))); }
|
||||
|
||||
|
||||
/** handles both block place and break events */
|
||||
@@ -219,13 +215,7 @@ public class SharedApi
|
||||
if (msBetweenLastLog >= MIN_MS_BETWEEN_OVERLOADED_LOG_MESSAGE)
|
||||
{
|
||||
lastOverloadedLogMessageMsTime = System.currentTimeMillis();
|
||||
|
||||
String message = "Distant Horizons overloaded, too many chunks queued for updating. " +
|
||||
"\nThis may result in holes in your LODs. " +
|
||||
"\nPlease move through the world slower, decrease your vanilla render distance, slow down your world pre-generator, or increase the Distant Horizons' CPU load config. " +
|
||||
"\nMax queue count ["+maxQueueCount+"] (["+MAX_UPDATING_CHUNK_COUNT_PER_THREAD+"] per thread).";
|
||||
ClientApi.INSTANCE.showChatMessageNextFrame(message);
|
||||
LOGGER.warn(message);
|
||||
LOGGER.warn("Too many chunks queued for updating, max queue count ["+maxQueueCount+"] (["+MAX_UPDATING_CHUNK_COUNT_PER_THREAD+"] per thread). This may result in holes in your LODs. Please move through the world slower, decrease your vanilla render distance, slow down your world pre-generator, or increase the CPU load config.");
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -320,18 +310,6 @@ public class SharedApi
|
||||
}
|
||||
|
||||
|
||||
// having a list of the nearby chunks is needed for lighting and beacon generation
|
||||
ArrayList<IChunkWrapper> nearbyChunkList;
|
||||
if (neighbourChunkList != null)
|
||||
{
|
||||
nearbyChunkList = neighbourChunkList;
|
||||
}
|
||||
else
|
||||
{
|
||||
nearbyChunkList = new ArrayList<>(1);
|
||||
nearbyChunkList.add(chunkWrapper);
|
||||
}
|
||||
|
||||
|
||||
// Save or populate the chunk wrapper's lighting
|
||||
// this is done so we don't have to worry about MC unloading the lighting data for this chunk
|
||||
@@ -341,7 +319,7 @@ public class SharedApi
|
||||
try
|
||||
{
|
||||
// If MC's lighting engine isn't thread safe this may cause the server thread to lag
|
||||
chunkWrapper.bakeDhLightingUsingMcLightingEngine();
|
||||
chunkWrapper.bakeDhLightingUsingMcLightingEngine(); // TODO handle unlit chunks, would pulling in the chunk from disk be a good idea? Look at ChunkLoader in the world gen code for an example
|
||||
}
|
||||
catch (IllegalStateException e)
|
||||
{
|
||||
@@ -351,16 +329,21 @@ public class SharedApi
|
||||
else
|
||||
{
|
||||
// generate the chunk's lighting, using neighboring chunks if present
|
||||
|
||||
ArrayList<IChunkWrapper> nearbyChunkList;
|
||||
if (neighbourChunkList != null)
|
||||
{
|
||||
nearbyChunkList = neighbourChunkList;
|
||||
}
|
||||
else
|
||||
{
|
||||
nearbyChunkList = new ArrayList<>(1);
|
||||
nearbyChunkList.add(chunkWrapper);
|
||||
}
|
||||
|
||||
DhLightingEngine.INSTANCE.lightChunk(chunkWrapper, nearbyChunkList, dhLevel.hasSkyLight() ? 15 : 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// get this chunk's active beacons
|
||||
List<BeaconBeamDTO> beaconBeamList = chunkWrapper.getAllActiveBeacons(nearbyChunkList);
|
||||
dhLevel.setBeaconBeamsForChunk(chunkWrapper.getChunkPos(), beaconBeamList);
|
||||
|
||||
|
||||
dhLevel.updateChunkAsync(chunkWrapper);
|
||||
dhLevel.setChunkHash(chunkWrapper.getChunkPos(), newChunkHash);
|
||||
}
|
||||
|
||||
@@ -20,20 +20,17 @@
|
||||
package com.seibel.distanthorizons.core.config;
|
||||
|
||||
|
||||
import com.seibel.distanthorizons.api.DhApi;
|
||||
import com.seibel.distanthorizons.api.enums.config.*;
|
||||
import com.seibel.distanthorizons.api.enums.config.quickOptions.*;
|
||||
import com.seibel.distanthorizons.api.enums.rendering.*;
|
||||
import com.seibel.distanthorizons.api.enums.worldGeneration.EDhApiDistantGeneratorMode;
|
||||
import com.seibel.distanthorizons.core.config.eventHandlers.*;
|
||||
import com.seibel.distanthorizons.core.config.eventHandlers.presets.*;
|
||||
import com.seibel.distanthorizons.core.config.listeners.ConfigChangeListener;
|
||||
import com.seibel.distanthorizons.core.config.types.*;
|
||||
import com.seibel.distanthorizons.core.config.types.enums.*;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import com.seibel.distanthorizons.coreapi.util.StringUtil;
|
||||
@@ -139,7 +136,6 @@ public class Config
|
||||
public static ConfigCategory fog = new ConfigCategory.Builder().set(Fog.class).build();
|
||||
public static ConfigCategory ssao = new ConfigCategory.Builder().set(Ssao.class).build();
|
||||
public static ConfigCategory noiseTextureSettings = new ConfigCategory.Builder().set(NoiseTextureSettings.class).build();
|
||||
public static ConfigCategory genericRendering = new ConfigCategory.Builder().set(GenericRendering.class).build();
|
||||
public static ConfigCategory advancedGraphics = new ConfigCategory.Builder().set(AdvancedGraphics.class).build();
|
||||
|
||||
|
||||
@@ -292,7 +288,7 @@ public class Config
|
||||
private static final Double FOG_RANGE_MAX = Math.sqrt(2.0);
|
||||
|
||||
public static ConfigEntry<Double> farFogStart = new ConfigEntry.Builder<Double>()
|
||||
.setMinDefaultMax(FOG_RANGE_MIN, 0.4, FOG_RANGE_MAX)
|
||||
.setMinDefaultMax(FOG_RANGE_MIN, 0.0, FOG_RANGE_MAX)
|
||||
.comment(""
|
||||
+ "At what distance should the far fog start? \n"
|
||||
+ "\n"
|
||||
@@ -523,8 +519,7 @@ public class Config
|
||||
public static ConfigEntry<Integer> noiseSteps = new ConfigEntry.Builder<Integer>()
|
||||
.setMinDefaultMax(1, 4, null)
|
||||
.comment(""
|
||||
+ "How many steps of noise should be applied to LODs?"
|
||||
+ "")
|
||||
+ "How many steps of noise should be applied to LODs?")
|
||||
.build();
|
||||
|
||||
public static ConfigEntry<Double> noiseIntensity = new ConfigEntry.Builder<Double>() // TODO: Make this a float (the ClassicConfigGUI doesn't support floats)
|
||||
@@ -537,34 +532,7 @@ public class Config
|
||||
.setMinDefaultMax(0, 1024, null)
|
||||
.comment(""
|
||||
+ "Defines how far should the noise texture render before it fades away. (in blocks) \n"
|
||||
+ "Set to 0 to disable noise from fading away \n"
|
||||
+ "")
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
public static class GenericRendering
|
||||
{
|
||||
public static ConfigEntry<Boolean> enableRendering = new ConfigEntry.Builder<Boolean>()
|
||||
.set(true)
|
||||
.comment(""
|
||||
+ "If true non terrain objects will be rendered in DH's terrain. \n"
|
||||
+ "This includes beacon beams and clouds. \n"
|
||||
+ "")
|
||||
.build();
|
||||
|
||||
public static ConfigEntry<Boolean> enableBeaconRendering = new ConfigEntry.Builder<Boolean>()
|
||||
.set(true)
|
||||
.comment(""
|
||||
+ "If true LOD beacon beams will be rendered. \n"
|
||||
+ "")
|
||||
.build();
|
||||
|
||||
public static ConfigEntry<Boolean> enableCloudRendering = new ConfigEntry.Builder<Boolean>()
|
||||
.set(true)
|
||||
.comment(""
|
||||
+ "If true LOD clouds will be rendered. \n"
|
||||
+ "")
|
||||
+ "Set to 0 to disable noise from fading away")
|
||||
.build();
|
||||
|
||||
}
|
||||
@@ -621,10 +589,8 @@ public class Config
|
||||
+ " does not have a ceiling.")
|
||||
.build();
|
||||
|
||||
@Deprecated
|
||||
public static ConfigEntry<Integer> caveCullingHeight = new ConfigEntry.Builder<Integer>()
|
||||
.setMinDefaultMax(-4096, 40, 4096)
|
||||
.setAppearance(EConfigEntryAppearance.ONLY_IN_API)
|
||||
.comment(""
|
||||
+ "At what Y value should cave culling start?")
|
||||
.build();
|
||||
@@ -795,20 +761,6 @@ public class Config
|
||||
+ "")
|
||||
.build();
|
||||
|
||||
public static ConfigEntry<Boolean> pullLightingForPregeneratedChunks = new ConfigEntry.Builder<Boolean>()
|
||||
.set(false)
|
||||
.comment(""
|
||||
+ "If true LOD generation for pre-existing chunks will attempt to pull the lighting data \n"
|
||||
+ "saved in Minecraft's Region files. \n"
|
||||
+ "If false DH will pull in chunks without lighting and re-light them. \n"
|
||||
+ " \n"
|
||||
+ "Setting this to true will result in faster LOD generation \n"
|
||||
+ "for already generated worlds, but is broken by most lighting mods. \n"
|
||||
+ " \n"
|
||||
+ "Set this to false if LODs are black. \n"
|
||||
+ "")
|
||||
.build();
|
||||
|
||||
public static ConfigEntry<EDhApiDataCompressionMode> dataCompression = new ConfigEntry.Builder<EDhApiDataCompressionMode>()
|
||||
.set(EDhApiDataCompressionMode.LZMA2)
|
||||
.comment(""
|
||||
@@ -857,47 +809,13 @@ public class Config
|
||||
+ "")
|
||||
.build();
|
||||
|
||||
public static ConfigEntry<String> ignoredRenderBlockCsv = new ConfigEntry.Builder<String>()
|
||||
.set("minecraft:barrier,minecraft:structure_void,minecraft:light,minecraft:tripwire")
|
||||
.comment(""
|
||||
+ "A comma separated list of block resource locations that won't be rendered by DH. \n"
|
||||
+ "Note: air is always included in this list. \n"
|
||||
+ "")
|
||||
.build();
|
||||
//public static ConfigEntry<Boolean> showMigrationChatWarning = new ConfigEntry.Builder<Boolean>()
|
||||
// .set(true)
|
||||
// .comment(""
|
||||
// + "Determines if a message should be displayed in the chat when LOD migration starts. \n"
|
||||
// + "")
|
||||
// .build();
|
||||
|
||||
public static ConfigEntry<String> ignoredRenderCaveBlockCsv = new ConfigEntry.Builder<String>()
|
||||
.set("minecraft:glow_lichen,minecraft:rail,minecraft:water,minecraft:lava,minecraft:bubble_column")
|
||||
.comment(""
|
||||
+ "A comma separated list of block resource locations that shouldn't be rendered \n"
|
||||
+ "if they are in a 0 sky light underground area. \n"
|
||||
+ "Note: air is always included in this list. \n"
|
||||
+ "")
|
||||
.build();
|
||||
|
||||
static
|
||||
{
|
||||
ignoredRenderBlockCsv.addListener(new ConfigChangeListener<String>(Config.Client.Advanced.LodBuilding.ignoredRenderBlockCsv,
|
||||
(blockCsv) ->
|
||||
{
|
||||
IWrapperFactory wrapperFactory = SingletonInjector.INSTANCE.get(IWrapperFactory.class);
|
||||
if (wrapperFactory != null)
|
||||
{
|
||||
wrapperFactory.resetRendererIgnoredBlocksSet();
|
||||
DhApi.Delayed.renderProxy.clearRenderDataCache();
|
||||
}
|
||||
}));
|
||||
|
||||
ignoredRenderCaveBlockCsv.addListener(new ConfigChangeListener<String>(Config.Client.Advanced.LodBuilding.ignoredRenderCaveBlockCsv,
|
||||
(blockCsv) ->
|
||||
{
|
||||
IWrapperFactory wrapperFactory = SingletonInjector.INSTANCE.get(IWrapperFactory.class);
|
||||
if (wrapperFactory != null)
|
||||
{
|
||||
wrapperFactory.resetRendererIgnoredCaveBlocks();
|
||||
DhApi.Delayed.renderProxy.clearRenderDataCache();
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
public static class Multiplayer
|
||||
@@ -1274,7 +1192,7 @@ public class Config
|
||||
// TODO default to error chat and info file
|
||||
public static ConfigEntry<EDhApiLoggerMode> logWorldGenEvent = new ConfigEntry.Builder<EDhApiLoggerMode>()
|
||||
.setServersideShortName("logWorldGenEvent")
|
||||
.set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT)
|
||||
.set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_FILE)
|
||||
.comment(""
|
||||
+ "If enabled, the mod will log information about the world generation process. \n"
|
||||
+ "This can be useful for debugging.")
|
||||
@@ -1282,7 +1200,7 @@ public class Config
|
||||
|
||||
public static ConfigEntry<EDhApiLoggerMode> logWorldGenPerformance = new ConfigEntry.Builder<EDhApiLoggerMode>()
|
||||
.setServersideShortName("logWorldGenPerformance")
|
||||
.set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT)
|
||||
.set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_FILE)
|
||||
.comment(""
|
||||
+ "If enabled, the mod will log performance about the world generation process. \n"
|
||||
+ "This can be useful for debugging.")
|
||||
@@ -1290,7 +1208,7 @@ public class Config
|
||||
|
||||
public static ConfigEntry<EDhApiLoggerMode> logWorldGenLoadEvent = new ConfigEntry.Builder<EDhApiLoggerMode>()
|
||||
.setServersideShortName("logWorldGenPerformance")
|
||||
.set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT)
|
||||
.set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_FILE)
|
||||
.comment(""
|
||||
+ "If enabled, the mod will log information about the world generation process. \n"
|
||||
+ "This can be useful for debugging.")
|
||||
@@ -1298,21 +1216,21 @@ public class Config
|
||||
|
||||
public static ConfigEntry<EDhApiLoggerMode> logLodBuilderEvent = new ConfigEntry.Builder<EDhApiLoggerMode>()
|
||||
.setServersideShortName("logLodBuilderEvent")
|
||||
.set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT)
|
||||
.set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE)
|
||||
.comment(""
|
||||
+ "If enabled, the mod will log information about the LOD generation process. \n"
|
||||
+ "This can be useful for debugging.")
|
||||
.build();
|
||||
|
||||
public static ConfigEntry<EDhApiLoggerMode> logRendererBufferEvent = new ConfigEntry.Builder<EDhApiLoggerMode>()
|
||||
.set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT)
|
||||
.set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE)
|
||||
.comment(""
|
||||
+ "If enabled, the mod will log information about the renderer buffer process. \n"
|
||||
+ "This can be useful for debugging.")
|
||||
.build();
|
||||
|
||||
public static ConfigEntry<EDhApiLoggerMode> logRendererGLEvent = new ConfigEntry.Builder<EDhApiLoggerMode>()
|
||||
.set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT)
|
||||
.set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE)
|
||||
.comment(""
|
||||
+ "If enabled, the mod will log information about the renderer OpenGL process. \n"
|
||||
+ "This can be useful for debugging.")
|
||||
@@ -1320,7 +1238,7 @@ public class Config
|
||||
|
||||
public static ConfigEntry<EDhApiLoggerMode> logFileReadWriteEvent = new ConfigEntry.Builder<EDhApiLoggerMode>()
|
||||
.setServersideShortName("logFileReadWriteEvent")
|
||||
.set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT)
|
||||
.set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE)
|
||||
.comment(""
|
||||
+ "If enabled, the mod will log information about file read/write operations. \n"
|
||||
+ "This can be useful for debugging.")
|
||||
@@ -1328,7 +1246,7 @@ public class Config
|
||||
|
||||
public static ConfigEntry<EDhApiLoggerMode> logFileSubDimEvent = new ConfigEntry.Builder<EDhApiLoggerMode>()
|
||||
.setServersideShortName("logFileSubDimEvent")
|
||||
.set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT)
|
||||
.set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE)
|
||||
.comment(""
|
||||
+ "If enabled, the mod will log information about file sub-dimension operations. \n"
|
||||
+ "This can be useful for debugging.")
|
||||
@@ -1336,7 +1254,7 @@ public class Config
|
||||
|
||||
public static ConfigEntry<EDhApiLoggerMode> logNetworkEvent = new ConfigEntry.Builder<EDhApiLoggerMode>()
|
||||
.setServersideShortName("logNetworkEvent")
|
||||
.set(EDhApiLoggerMode.LOG_ERROR_TO_CHAT)
|
||||
.set(EDhApiLoggerMode.LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE)
|
||||
.comment(""
|
||||
+ "If enabled, the mod will log information about network operations. \n"
|
||||
+ "This can be useful for debugging.")
|
||||
@@ -1350,13 +1268,6 @@ public class Config
|
||||
+ "memory allocated to run DH well.")
|
||||
.build();
|
||||
|
||||
public static ConfigEntry<Boolean> showReplayWarningOnStartup = new ConfigEntry.Builder<Boolean>()
|
||||
.set(true)
|
||||
.comment(""
|
||||
+ "If enabled, a chat message will be displayed when a replay is started \n"
|
||||
+ "giving some basic information about how DH will function.")
|
||||
.build();
|
||||
|
||||
}
|
||||
|
||||
public static class Debugging
|
||||
@@ -1424,15 +1335,6 @@ public class Config
|
||||
+ "")
|
||||
.build();
|
||||
|
||||
public static ConfigEntry<Boolean> logBufferGarbageCollection = new ConfigEntry.Builder<Boolean>()
|
||||
.set(false)
|
||||
.comment(""
|
||||
+ "If true OpenGL Buffer garbage collection will be logged \n"
|
||||
+ "this also includes the number of live buffers. \n"
|
||||
+ "")
|
||||
.build();
|
||||
|
||||
|
||||
// Note: This will reset on game restart, and should have a warning on the tooltip
|
||||
public static ConfigEntry<Boolean> allowUnsafeValues = new ConfigEntry.Builder<Boolean>()
|
||||
.set(false)
|
||||
|
||||
@@ -260,38 +260,20 @@ public class ConfigEntry<T> extends AbstractConfigType<T, ConfigEntry<T>> implem
|
||||
public byte isValid(T value, T min, T max)
|
||||
{
|
||||
if (this.configBase.disableMinMax)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else if (min == null && max == null)
|
||||
{
|
||||
// no validation is needed for this field
|
||||
return 0;
|
||||
}
|
||||
else if (value == null || this.value == null
|
||||
|| value.getClass() != this.value.getClass())
|
||||
{
|
||||
// If the 2 variables aren't the same type then it will be invalid
|
||||
|
||||
if (value == null || this.value == null || value.getClass() != this.value.getClass()) // If the 2 variables aren't the same type then it will be invalid
|
||||
return 2;
|
||||
}
|
||||
else if (Number.class.isAssignableFrom(value.getClass()))
|
||||
{
|
||||
// Only check min max if it is a number
|
||||
if (Number.class.isAssignableFrom(value.getClass()))
|
||||
{ // Only check min max if it is a number
|
||||
if (max != null && NumberUtil.greaterThan((Number) value, (Number) max))
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
if (min != null && NumberUtil.lessThan((Number) value, (Number) min))
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** This should normally not be called since set() automatically calls this */
|
||||
|
||||
@@ -27,7 +27,6 @@ import com.seibel.distanthorizons.core.config.types.enums.EConfigEntryAppearance
|
||||
*
|
||||
* @author coolGi
|
||||
*/
|
||||
@Deprecated // FIXME doesn't work with localization
|
||||
public class ConfigLinkedEntry extends AbstractConfigType<AbstractConfigType<?, ?>, ConfigLinkedEntry>
|
||||
{
|
||||
public ConfigLinkedEntry(AbstractConfigType<?, ?> value)
|
||||
|
||||
-2
@@ -62,8 +62,6 @@ public class FullDataSourceV2 implements IDataSource<IDhLevel>
|
||||
|
||||
/** measured in data columns */
|
||||
public static final int WIDTH = 64;
|
||||
/** how many chunks wide this datasource is. */
|
||||
public static final int NUMB_OF_CHUNKS_WIDE = WIDTH / LodUtil.CHUNK_WIDTH;
|
||||
|
||||
public static final byte DATA_FORMAT_VERSION = 1;
|
||||
|
||||
|
||||
+1
-1
@@ -182,7 +182,7 @@ public class ColumnRenderSource implements IDataSource<IDhClientLevel>
|
||||
EDhApiWorldGenerationStep worldGenStep = inputFullDataSource.getWorldGenStepAtRelativePos(x, z);
|
||||
if (dataColumn != null && worldGenStep != EDhApiWorldGenerationStep.EMPTY)
|
||||
{
|
||||
FullDataToRenderDataTransformer.updateRenderDataViewWithFullDataColumn(
|
||||
FullDataToRenderDataTransformer.convertColumnData(
|
||||
level, inputFullDataSource.mapping,
|
||||
minBlockPos.x + x,
|
||||
minBlockPos.z + z,
|
||||
|
||||
+2
-3
@@ -19,7 +19,6 @@
|
||||
|
||||
package com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
||||
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||
@@ -476,10 +475,10 @@ public class ColumnBox
|
||||
throw new RuntimeException("Loop error");
|
||||
if (previousAdjDepth > adjYMax)
|
||||
{
|
||||
if (irisBlockMaterialId == EDhApiBlockMaterial.GRASS.index)
|
||||
if (irisBlockMaterialId == IBlockStateWrapper.IrisBlockMaterial.GRASS)
|
||||
{
|
||||
// this LOD is underneath another, grass will never show here
|
||||
irisBlockMaterialId = EDhApiBlockMaterial.DIRT.index;
|
||||
irisBlockMaterialId = IBlockStateWrapper.IrisBlockMaterial.DIRT;
|
||||
}
|
||||
|
||||
builder.addQuadAdj(direction, x, adjYMax, z, horizontalWidth, (short) (previousAdjDepth - adjYMax), color, irisBlockMaterialId,
|
||||
|
||||
+2
-5
@@ -50,11 +50,8 @@ public class ColumnRenderBuffer implements AutoCloseable
|
||||
|
||||
private static final long MAX_BUFFER_UPLOAD_TIMEOUT_NANOSECONDS = 1_000_000;
|
||||
|
||||
/** number of bytes a single quad takes */
|
||||
public static final int QUADS_BYTE_SIZE = LodUtil.LOD_VERTEX_FORMAT.getByteSize() * 4;
|
||||
/** how big a single VBO can be in bytes */
|
||||
public static final int MAX_VBO_BYTE_SIZE = 10 * 1024 * 1024; // 10 MB
|
||||
public static final int MAX_QUADS_PER_BUFFER = MAX_VBO_BYTE_SIZE / QUADS_BYTE_SIZE;
|
||||
public static final int QUADS_BYTE_SIZE = LodUtil.LOD_VERTEX_FORMAT.getByteSize() * 4; // TODO what does the 4 represent
|
||||
public static final int MAX_QUADS_PER_BUFFER = (1024 * 1024 * 1) / QUADS_BYTE_SIZE; // TODO what do these multiples represent?
|
||||
public static final int FULL_SIZED_BUFFER = MAX_QUADS_PER_BUFFER * QUADS_BYTE_SIZE;
|
||||
|
||||
|
||||
|
||||
+26
-2
@@ -54,6 +54,11 @@ public class ColumnRenderBufferBuilder
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
|
||||
public static final int MAX_NUMBER_OF_CONCURRENT_CALLS_PER_THREAD = 3;
|
||||
public static int maxNumberOfConcurrentCalls = MAX_NUMBER_OF_CONCURRENT_CALLS_PER_THREAD;
|
||||
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// vbo building //
|
||||
@@ -82,14 +87,33 @@ public class ColumnRenderBufferBuilder
|
||||
{
|
||||
boolean enableTransparency = Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled;
|
||||
|
||||
//EVENT_LOGGER.trace("RenderRegion start QuadBuild @ " + renderSource.sectionPos);
|
||||
boolean enableSkyLightCulling =
|
||||
Config.Client.Advanced.Graphics.AdvancedGraphics.enableCaveCulling.get()
|
||||
&& (
|
||||
// dimensions with a ceiling will be all caves so we don't want cave culling
|
||||
!clientLevel.getLevelWrapper().hasCeiling()
|
||||
// the end has a lot of overhangs with 0 lighting above the void, which look broken with
|
||||
// the current cave culling logic (this could probably be improved, but just skipping it works best for now)
|
||||
&& !clientLevel.getLevelWrapper().getDimensionType().isTheEnd()
|
||||
// FIXME temporary fix
|
||||
// Cave culling is currently broken for any detail level above 0
|
||||
&& DhSectionPos.getDetailLevel(renderSource.pos) == DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL
|
||||
);
|
||||
|
||||
int skyLightCullingBelow = Config.Client.Advanced.Graphics.AdvancedGraphics.caveCullingHeight.get();
|
||||
// FIXME: Clamp also to the max world height.
|
||||
skyLightCullingBelow = Math.max(skyLightCullingBelow, clientLevel.getMinY());
|
||||
|
||||
|
||||
long builderStartTime = System.currentTimeMillis();
|
||||
|
||||
LodQuadBuilder builder = new LodQuadBuilder(enableTransparency, clientLevel.getClientLevelWrapper());
|
||||
LodQuadBuilder builder = new LodQuadBuilder(enableSkyLightCulling, (short) (skyLightCullingBelow - clientLevel.getMinY()), enableTransparency, clientLevel.getClientLevelWrapper());
|
||||
makeLodRenderData(builder, renderSource, adjData);
|
||||
|
||||
long builderEndTime = System.currentTimeMillis();
|
||||
long buildMs = builderEndTime - builderStartTime;
|
||||
//LOGGER.debug("RenderRegion end QuadBuild @ " + renderSource.pos + " took: " + buildMs);
|
||||
LOGGER.debug("RenderRegion end QuadBuild @ " + renderSource.pos + " took: " + buildMs);
|
||||
|
||||
return builder;
|
||||
}
|
||||
|
||||
+17
-19
@@ -19,7 +19,6 @@
|
||||
|
||||
package com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dataObjects.render.ColumnRenderSource;
|
||||
import com.seibel.distanthorizons.core.pos.DhLodPos;
|
||||
@@ -96,54 +95,53 @@ public class CubicLodTemplate
|
||||
}
|
||||
case SHOW_BLOCK_MATERIAL:
|
||||
{
|
||||
|
||||
switch (EDhApiBlockMaterial.getFromIndex(blockMaterialId))
|
||||
switch (blockMaterialId)
|
||||
{
|
||||
case UNKNOWN:
|
||||
case AIR: // shouldn't normally be rendered, but just in case
|
||||
case IBlockStateWrapper.IrisBlockMaterial.UNKOWN:
|
||||
case IBlockStateWrapper.IrisBlockMaterial.AIR: // shouldn't normally be rendered, but just in case
|
||||
color = ColorUtil.HOT_PINK;
|
||||
break;
|
||||
|
||||
case LEAVES:
|
||||
case IBlockStateWrapper.IrisBlockMaterial.LEAVES:
|
||||
color = ColorUtil.DARK_GREEN;
|
||||
break;
|
||||
case STONE:
|
||||
case IBlockStateWrapper.IrisBlockMaterial.STONE:
|
||||
color = ColorUtil.GRAY;
|
||||
break;
|
||||
case WOOD:
|
||||
case IBlockStateWrapper.IrisBlockMaterial.WOOD:
|
||||
color = ColorUtil.BROWN;
|
||||
break;
|
||||
case METAL:
|
||||
case IBlockStateWrapper.IrisBlockMaterial.METAL:
|
||||
color = ColorUtil.DARK_GRAY;
|
||||
break;
|
||||
case DIRT:
|
||||
case IBlockStateWrapper.IrisBlockMaterial.DIRT:
|
||||
color = ColorUtil.LIGHT_BROWN;
|
||||
break;
|
||||
case LAVA:
|
||||
case IBlockStateWrapper.IrisBlockMaterial.LAVA:
|
||||
color = ColorUtil.ORANGE;
|
||||
break;
|
||||
case DEEPSLATE:
|
||||
case IBlockStateWrapper.IrisBlockMaterial.DEEPSLATE:
|
||||
color = ColorUtil.BLACK;
|
||||
break;
|
||||
case SNOW:
|
||||
case IBlockStateWrapper.IrisBlockMaterial.SNOW:
|
||||
color = ColorUtil.WHITE;
|
||||
break;
|
||||
case SAND:
|
||||
case IBlockStateWrapper.IrisBlockMaterial.SAND:
|
||||
color = ColorUtil.TAN;
|
||||
break;
|
||||
case TERRACOTTA:
|
||||
case IBlockStateWrapper.IrisBlockMaterial.TERRACOTTA:
|
||||
color = ColorUtil.DARK_ORANGE;
|
||||
break;
|
||||
case NETHER_STONE:
|
||||
case IBlockStateWrapper.IrisBlockMaterial.NETHER_STONE:
|
||||
color = ColorUtil.DARK_RED;
|
||||
break;
|
||||
case WATER:
|
||||
case IBlockStateWrapper.IrisBlockMaterial.WATER:
|
||||
color = ColorUtil.BLUE;
|
||||
break;
|
||||
case GRASS:
|
||||
case IBlockStateWrapper.IrisBlockMaterial.GRASS:
|
||||
color = ColorUtil.GREEN;
|
||||
break;
|
||||
case ILLUMINATED:
|
||||
case IBlockStateWrapper.IrisBlockMaterial.ILLUMINATED:
|
||||
color = ColorUtil.YELLOW;
|
||||
break;
|
||||
|
||||
|
||||
+4
-7
@@ -24,7 +24,6 @@ import java.nio.ByteOrder;
|
||||
import java.util.*;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiGrassSideRendering;
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial;
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiDebugRendering;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
@@ -51,9 +50,7 @@ public class LodQuadBuilder
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
|
||||
@Deprecated
|
||||
public final boolean skipQuadsWithZeroSkylight;
|
||||
@Deprecated
|
||||
public final short skyLightCullingBelow;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@@ -125,7 +122,7 @@ public class LodQuadBuilder
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public LodQuadBuilder(boolean doTransparency, IClientLevelWrapper clientLevelWrapper)
|
||||
public LodQuadBuilder(boolean enableSkylightCulling, short skyLightCullingBelow, boolean doTransparency, IClientLevelWrapper clientLevelWrapper)
|
||||
{
|
||||
this.doTransparency = doTransparency;
|
||||
for (int i = 0; i < 6; i++)
|
||||
@@ -134,8 +131,8 @@ public class LodQuadBuilder
|
||||
this.transparentQuads[i] = new ArrayList<>();
|
||||
}
|
||||
|
||||
this.skipQuadsWithZeroSkylight = false;
|
||||
this.skyLightCullingBelow = 0;
|
||||
this.skipQuadsWithZeroSkylight = enableSkylightCulling;
|
||||
this.skyLightCullingBelow = skyLightCullingBelow;
|
||||
this.clientLevelWrapper = clientLevelWrapper;
|
||||
|
||||
this.debugRenderingMode = Config.Client.Advanced.Debugging.debugRendering.get();
|
||||
@@ -276,7 +273,7 @@ public class LodQuadBuilder
|
||||
int color = quad.color;
|
||||
|
||||
// use custom side color logic for grass blocks
|
||||
if (quad.irisBlockMaterialId == EDhApiBlockMaterial.GRASS.index)
|
||||
if (quad.irisBlockMaterialId == IBlockStateWrapper.IrisBlockMaterial.GRASS)
|
||||
{
|
||||
// only use dirt colors if debug rendering is disabled
|
||||
if (this.debugRenderingMode == EDhApiDebugRendering.OFF)
|
||||
|
||||
+94
-132
@@ -20,7 +20,6 @@
|
||||
package com.seibel.distanthorizons.core.dataObjects.transformers;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiBlocksToAvoid;
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.FullDataPointIdMap;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||
@@ -33,7 +32,6 @@ import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||
import com.seibel.distanthorizons.core.util.FullDataPointUtil;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.RenderDataPointUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||
@@ -111,85 +109,74 @@ public class FullDataToRenderDataTransformer
|
||||
}
|
||||
|
||||
columnSource.markNotEmpty();
|
||||
int baseX = DhSectionPos.getMinCornerBlockX(pos);
|
||||
int baseZ = DhSectionPos.getMinCornerBlockZ(pos);
|
||||
|
||||
for (int x = 0; x < DhSectionPos.getWidthCountForLowerDetailedSection(pos, dataDetail); x++)
|
||||
if (dataDetail == columnSource.getDataDetailLevel())
|
||||
{
|
||||
for (int z = 0; z < DhSectionPos.getWidthCountForLowerDetailedSection(pos, dataDetail); z++)
|
||||
{
|
||||
throwIfThreadInterrupted();
|
||||
|
||||
ColumnArrayView columnArrayView = columnSource.getVerticalDataPointView(x, z);
|
||||
LongArrayList dataColumn = fullDataSource.get(x, z);
|
||||
updateRenderDataViewWithFullDataColumn(level, fullDataSource.mapping, baseX + x, baseZ + z, columnArrayView, dataColumn);
|
||||
}
|
||||
}
|
||||
|
||||
columnSource.fillDebugFlag(0, 0, ColumnRenderSource.SECTION_SIZE, ColumnRenderSource.SECTION_SIZE, ColumnRenderSource.DebugSourceFlag.FULL);
|
||||
int baseX = DhSectionPos.getMinCornerBlockX(pos);
|
||||
int baseZ = DhSectionPos.getMinCornerBlockZ(pos);
|
||||
|
||||
for (int x = 0; x < DhSectionPos.getWidthCountForLowerDetailedSection(pos, dataDetail); x++)
|
||||
{
|
||||
for (int z = 0; z < DhSectionPos.getWidthCountForLowerDetailedSection(pos, dataDetail); z++)
|
||||
{
|
||||
throwIfThreadInterrupted();
|
||||
|
||||
ColumnArrayView columnArrayView = columnSource.getVerticalDataPointView(x, z);
|
||||
LongArrayList dataColumn = fullDataSource.get(x, z);
|
||||
convertColumnData(level, fullDataSource.mapping, baseX + x, baseZ + z, columnArrayView, dataColumn);
|
||||
}
|
||||
}
|
||||
|
||||
columnSource.fillDebugFlag(0, 0, ColumnRenderSource.SECTION_SIZE, ColumnRenderSource.SECTION_SIZE, ColumnRenderSource.DebugSourceFlag.FULL);
|
||||
|
||||
return columnSource;
|
||||
}
|
||||
|
||||
/** Updates the given {@link ColumnArrayView} to match the incoming Full data {@link LongArrayList} */
|
||||
public static void updateRenderDataViewWithFullDataColumn(
|
||||
IDhClientLevel level,
|
||||
FullDataPointIdMap fullDataMapping, int blockX, int blockZ,
|
||||
ColumnArrayView columnArrayView,
|
||||
LongArrayList fullDataColumn)
|
||||
{
|
||||
if (fullDataColumn == null || fullDataColumn.size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int dataTotalLength = fullDataColumn.size();
|
||||
if (dataTotalLength > columnArrayView.verticalSize())
|
||||
{
|
||||
ColumnArrayView totalColumnData = new ColumnArrayView(new LongArrayList(new long[dataTotalLength]), dataTotalLength, 0, dataTotalLength);
|
||||
iterateAndConvert(level, fullDataMapping, blockX, blockZ, totalColumnData, fullDataColumn);
|
||||
columnArrayView.changeVerticalSizeFrom(totalColumnData);
|
||||
}
|
||||
else
|
||||
{
|
||||
iterateAndConvert(level, fullDataMapping, blockX, blockZ, columnArrayView, fullDataColumn); //Directly use the arrayView since it fits.
|
||||
throw new UnsupportedOperationException("To be implemented");
|
||||
//FIXME: Implement different size creation of renderData
|
||||
}
|
||||
return columnSource;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper methods //
|
||||
//================//
|
||||
|
||||
/**
|
||||
* Called in loops that may run for an extended period of time. <br>
|
||||
* This is necessary to allow canceling these transformers since running
|
||||
* them after the client has left a given world will throw exceptions.
|
||||
*/
|
||||
private static void throwIfThreadInterrupted() throws InterruptedException
|
||||
{
|
||||
if (Thread.interrupted())
|
||||
{
|
||||
throw new InterruptedException(FullDataToRenderDataTransformer.class.getSimpleName() + " task interrupted.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// TODO what does this mean?
|
||||
private static void iterateAndConvert(
|
||||
IDhClientLevel level, FullDataPointIdMap fullDataMapping,
|
||||
int blockX, int blockZ,
|
||||
IDhClientLevel level, FullDataPointIdMap fullDataMapping,
|
||||
int blockX, int blockZ,
|
||||
ColumnArrayView renderColumnData, LongArrayList fullColumnData)
|
||||
{
|
||||
boolean ignoreNonCollidingBlocks = (Config.Client.Advanced.Graphics.Quality.blocksToIgnore.get() == EDhApiBlocksToAvoid.NON_COLLIDING);
|
||||
boolean avoidSolidBlocks = (Config.Client.Advanced.Graphics.Quality.blocksToIgnore.get() == EDhApiBlocksToAvoid.NON_COLLIDING);
|
||||
boolean colorBelowWithAvoidedBlocks = Config.Client.Advanced.Graphics.Quality.tintWithAvoidedBlocks.get();
|
||||
|
||||
HashSet<IBlockStateWrapper> blockStatesToIgnore = WRAPPER_FACTORY.getRendererIgnoredBlocks(level.getLevelWrapper());
|
||||
HashSet<IBlockStateWrapper> caveBlockStatesToIgnore = WRAPPER_FACTORY.getRendererIgnoredCaveBlocks(level.getLevelWrapper());
|
||||
|
||||
boolean caveCullingEnabled =
|
||||
Config.Client.Advanced.Graphics.AdvancedGraphics.enableCaveCulling.get()
|
||||
&& (
|
||||
// dimensions with a ceiling will be all caves so we don't want cave culling
|
||||
!level.getLevelWrapper().hasCeiling()
|
||||
// the end has a lot of overhangs with 0 lighting above the void, which look broken with
|
||||
// the current cave culling logic (this could probably be improved, but just skipping it works best for now)
|
||||
&& !level.getLevelWrapper().getDimensionType().isTheEnd()
|
||||
);
|
||||
|
||||
boolean isVoid = true;
|
||||
|
||||
int colorToApplyToNextBlock = -1;
|
||||
int lastColor = 0;
|
||||
int lastBottom = -10000;
|
||||
|
||||
int skylightToApplyToNextBlock = -1;
|
||||
int blocklightToApplyToNextBlock = -1;
|
||||
int columnOffset = 0;
|
||||
|
||||
IBiomeWrapper biome = null;
|
||||
IBlockStateWrapper block = null;
|
||||
|
||||
|
||||
// goes from the top down
|
||||
for (int i = 0; i < fullColumnData.size(); i++)
|
||||
{
|
||||
@@ -200,6 +187,23 @@ public class FullDataToRenderDataTransformer
|
||||
int blockLight = FullDataPointUtil.getBlockLight(fullData);
|
||||
int skyLight = FullDataPointUtil.getSkyLight(fullData);
|
||||
|
||||
// TODO how should corrupted data be handled?
|
||||
// TODO why is the full data corrupted in the first place? FullDataPointUtil hasn't been changed in a long time, could one of the full data point objects be corrupted?
|
||||
// TODO if either of these happen the ID might also be invalid
|
||||
//if (bottomY + blockHeight > 300)
|
||||
//{
|
||||
// // this data point is too tall, it's probably a monolith
|
||||
// int k = 0;
|
||||
// throw new RuntimeException();
|
||||
//}
|
||||
//if (light > 16 || light < 0)
|
||||
//{
|
||||
// // light is out of range
|
||||
// throw new RuntimeException();
|
||||
//}
|
||||
|
||||
IBiomeWrapper biome;
|
||||
IBlockStateWrapper block;
|
||||
try
|
||||
{
|
||||
biome = fullDataMapping.getBiomeWrapper(id);
|
||||
@@ -224,72 +228,28 @@ public class FullDataToRenderDataTransformer
|
||||
}
|
||||
|
||||
|
||||
//====================//
|
||||
// ignored block and //
|
||||
// cave culling check //
|
||||
//====================//
|
||||
|
||||
boolean ignoreBlock = blockStatesToIgnore.contains(block);
|
||||
boolean caveBlock = caveBlockStatesToIgnore.contains(block);
|
||||
if (caveBlock)
|
||||
if (blockStatesToIgnore.contains(block))
|
||||
{
|
||||
if (caveCullingEnabled
|
||||
// assume this data point is underground if it has no sky-light
|
||||
&& skyLight == LodUtil.MIN_MC_LIGHT
|
||||
// cave culling shouldn't happen when at the top of the world
|
||||
&& columnOffset != 0
|
||||
// cave culling can't happen when at the bottom of the world
|
||||
&& columnOffset != fullColumnData.size())
|
||||
{
|
||||
// we need to get the next sky/block lights because
|
||||
// the air block here will always have a light of 0/0 due to only the top of the LOD's light being saved.
|
||||
long nextFullData = fullColumnData.getLong(i+1);
|
||||
int nextSkyLight = FullDataPointUtil.getSkyLight(nextFullData);
|
||||
|
||||
if (nextSkyLight == LodUtil.MIN_MC_LIGHT
|
||||
&& ColorUtil.getAlpha(lastColor) == 255)
|
||||
{
|
||||
// replace the previous block with new bottom
|
||||
long columnData = renderColumnData.get(columnOffset - 1);
|
||||
columnData = RenderDataPointUtil.setYMin(columnData, bottomY);
|
||||
renderColumnData.set(columnOffset - 1, columnData);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
if (ignoreBlock)
|
||||
{
|
||||
// this is a merged block and a cave block, so it should never be rendered
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else if (ignoreBlock)
|
||||
{
|
||||
// this is an ignored block, but shouldn't be merged like a cave block
|
||||
// Don't render: air, barriers, light blocks, etc.
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
//===================//
|
||||
// solid block check //
|
||||
//===================//
|
||||
|
||||
if (ignoreNonCollidingBlocks && !block.isSolid() && !block.isLiquid() && block.getOpacity() != LodUtil.BLOCK_FULLY_OPAQUE)
|
||||
// solid block check
|
||||
if (avoidSolidBlocks && !block.isSolid() && !block.isLiquid() && block.getOpacity() != IBlockStateWrapper.FULLY_OPAQUE)
|
||||
{
|
||||
if (colorBelowWithAvoidedBlocks)
|
||||
{
|
||||
int tempColor = level.computeBaseColor(new DhBlockPos(blockX, bottomY + level.getMinY(), blockZ), biome, block);
|
||||
// don't transfer the color when alpha is 0
|
||||
if (ColorUtil.getAlpha(tempColor) != 0)
|
||||
if (ColorUtil.getAlpha(tempColor) == 0)
|
||||
{
|
||||
// don't transfer alpha if for some reason grass is semi transparent
|
||||
colorToApplyToNextBlock = ColorUtil.setAlpha(tempColor,255);
|
||||
|
||||
skylightToApplyToNextBlock = skyLight;
|
||||
blocklightToApplyToNextBlock = blockLight;
|
||||
//make sure to not transfer the color when alpha is 0
|
||||
continue;
|
||||
}
|
||||
//mare sure to not trnasfer alpha if for some reason grass is semi transparent
|
||||
colorToApplyToNextBlock = ColorUtil.setAlpha(tempColor,255);
|
||||
skylightToApplyToNextBlock = skyLight;
|
||||
blocklightToApplyToNextBlock = blockLight;
|
||||
}
|
||||
|
||||
// don't add this block
|
||||
@@ -311,11 +271,11 @@ public class FullDataToRenderDataTransformer
|
||||
skyLight = skylightToApplyToNextBlock;
|
||||
blockLight = blocklightToApplyToNextBlock;
|
||||
}
|
||||
|
||||
//check if they share a top-bottom face and if they have same color
|
||||
|
||||
//check if they share a top-bottom face and if they have same collor
|
||||
if (color == lastColor && bottomY + blockHeight == lastBottom && columnOffset > 0)
|
||||
{
|
||||
//replace the previous block with new bottom
|
||||
//replace the previus block with new bottom
|
||||
long columnData = renderColumnData.get(columnOffset - 1);
|
||||
columnData = RenderDataPointUtil.setYMin(columnData, bottomY);
|
||||
renderColumnData.set(columnOffset - 1, columnData);
|
||||
@@ -324,13 +284,13 @@ public class FullDataToRenderDataTransformer
|
||||
{
|
||||
// add the block
|
||||
isVoid = false;
|
||||
long columnData = RenderDataPointUtil.createDataPoint(bottomY + blockHeight, bottomY, color, skyLight, blockLight, block.getMaterialId());
|
||||
long columnData = RenderDataPointUtil.createDataPoint(bottomY + blockHeight, bottomY, color, skyLight, blockLight, block.getIrisBlockMaterialId());
|
||||
renderColumnData.set(columnOffset, columnData);
|
||||
columnOffset++;
|
||||
}
|
||||
lastBottom = bottomY;
|
||||
lastColor = color;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -340,22 +300,24 @@ public class FullDataToRenderDataTransformer
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper methods //
|
||||
//================//
|
||||
|
||||
/**
|
||||
* Called in loops that may run for an extended period of time. <br>
|
||||
* This is necessary to allow canceling these transformers since running
|
||||
* them after the client has left a given world will throw exceptions.
|
||||
*/
|
||||
private static void throwIfThreadInterrupted() throws InterruptedException
|
||||
// TODO what does this mean?
|
||||
public static void convertColumnData(IDhClientLevel level, FullDataPointIdMap fullDataMapping, int blockX, int blockZ, ColumnArrayView columnArrayView, LongArrayList fullDataColumn)
|
||||
{
|
||||
if (Thread.interrupted())
|
||||
if (fullDataColumn == null || fullDataColumn.size() == 0)
|
||||
{
|
||||
throw new InterruptedException(FullDataToRenderDataTransformer.class.getSimpleName() + " task interrupted.");
|
||||
return;
|
||||
}
|
||||
|
||||
int dataTotalLength = fullDataColumn.size();
|
||||
if (dataTotalLength > columnArrayView.verticalSize())
|
||||
{
|
||||
ColumnArrayView totalColumnData = new ColumnArrayView(new LongArrayList(new long[dataTotalLength]), dataTotalLength, 0, dataTotalLength);
|
||||
iterateAndConvert(level, fullDataMapping, blockX, blockZ, totalColumnData, fullDataColumn);
|
||||
columnArrayView.changeVerticalSizeFrom(totalColumnData);
|
||||
}
|
||||
else
|
||||
{
|
||||
iterateAndConvert(level, fullDataMapping, blockX, blockZ, columnArrayView, fullDataColumn); //Directly use the arrayView since it fits.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+26
-41
@@ -31,6 +31,7 @@ import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.util.FullDataPointUtil;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
@@ -46,6 +47,8 @@ public class LodDataBuilder
|
||||
{
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
private static final IBlockStateWrapper AIR = SingletonInjector.INSTANCE.get(IWrapperFactory.class).getAirBlockStateWrapper();
|
||||
/** how many chunks wide the {@link FullDataSourceV2} is. */
|
||||
private static final int NUMB_OF_CHUNKS_WIDE = FullDataSourceV2.WIDTH / LodUtil.CHUNK_WIDTH;
|
||||
|
||||
private static boolean getTopErrorLogged = false;
|
||||
|
||||
@@ -64,8 +67,12 @@ public class LodDataBuilder
|
||||
|
||||
|
||||
|
||||
int sectionPosX = getXOrZSectionPosFromChunkPos(chunkWrapper.getChunkPos().x);
|
||||
int sectionPosZ = getXOrZSectionPosFromChunkPos(chunkWrapper.getChunkPos().z);
|
||||
// get the section position
|
||||
int sectionPosX = chunkWrapper.getChunkPos().x;
|
||||
// negative positions start at -1 so the logic there is slightly different
|
||||
sectionPosX = (sectionPosX < 0) ? ((sectionPosX + 1) / NUMB_OF_CHUNKS_WIDE) - 1 : (sectionPosX / NUMB_OF_CHUNKS_WIDE);
|
||||
int sectionPosZ = chunkWrapper.getChunkPos().z;
|
||||
sectionPosZ = (sectionPosZ < 0) ? ((sectionPosZ + 1) / NUMB_OF_CHUNKS_WIDE) - 1 : (sectionPosZ / NUMB_OF_CHUNKS_WIDE);
|
||||
long pos = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ);
|
||||
|
||||
FullDataSourceV2 dataSource = FullDataSourceV2.createEmpty(pos);
|
||||
@@ -91,30 +98,30 @@ public class LodDataBuilder
|
||||
// -3 -> 1
|
||||
// -4 -> 0 ---
|
||||
// -5 -> 3
|
||||
chunkOffsetX = ((chunkOffsetX) % FullDataSourceV2.NUMB_OF_CHUNKS_WIDE);
|
||||
chunkOffsetX = ((chunkOffsetX) % NUMB_OF_CHUNKS_WIDE);
|
||||
if (chunkOffsetX != 0)
|
||||
{
|
||||
chunkOffsetX += FullDataSourceV2.NUMB_OF_CHUNKS_WIDE;
|
||||
chunkOffsetX += NUMB_OF_CHUNKS_WIDE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
chunkOffsetX %= FullDataSourceV2.NUMB_OF_CHUNKS_WIDE;
|
||||
chunkOffsetX %= NUMB_OF_CHUNKS_WIDE;
|
||||
}
|
||||
chunkOffsetX *= LodUtil.CHUNK_WIDTH;
|
||||
|
||||
int chunkOffsetZ = chunkWrapper.getChunkPos().z;
|
||||
if (chunkWrapper.getChunkPos().z < 0)
|
||||
{
|
||||
chunkOffsetZ = ((chunkOffsetZ) % FullDataSourceV2.NUMB_OF_CHUNKS_WIDE);
|
||||
chunkOffsetZ = ((chunkOffsetZ) % NUMB_OF_CHUNKS_WIDE);
|
||||
if (chunkOffsetZ != 0)
|
||||
{
|
||||
chunkOffsetZ += FullDataSourceV2.NUMB_OF_CHUNKS_WIDE;
|
||||
chunkOffsetZ += NUMB_OF_CHUNKS_WIDE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
chunkOffsetZ %= FullDataSourceV2.NUMB_OF_CHUNKS_WIDE;
|
||||
chunkOffsetZ %= NUMB_OF_CHUNKS_WIDE;
|
||||
}
|
||||
chunkOffsetZ *= LodUtil.CHUNK_WIDTH;
|
||||
|
||||
@@ -205,7 +212,6 @@ public class LodDataBuilder
|
||||
longs.add(FullDataPointUtil.encode(mappedId, lastY - y, y + 1 - chunkWrapper.getMinBuildHeight(), blockLight, skyLight));
|
||||
biome = newBiome;
|
||||
blockState = newBlockState;
|
||||
|
||||
mappedId = dataSource.mapping.addIfNotPresentAndGetId(biome, blockState);
|
||||
blockLight = newBlockLight;
|
||||
skyLight = newSkyLight;
|
||||
@@ -290,28 +296,19 @@ public class LodDataBuilder
|
||||
|
||||
// this block isn't on a chunk boundary, check if it is next to a transparent/air block
|
||||
IBlockStateWrapper blockState = chunkWrapper.getBlockState(testBlockPos);
|
||||
return blockState.isAir() || blockState.getOpacity() != LodUtil.BLOCK_FULLY_OPAQUE;
|
||||
return blockState.isAir() || blockState.getOpacity() != IBlockStateWrapper.FULLY_OPAQUE;
|
||||
}
|
||||
|
||||
|
||||
/** @throws ClassCastException if an API user returns the wrong object type(s) */
|
||||
public static FullDataSourceV2 createFromApiChunkData(DhApiChunk apiChunk) throws ClassCastException, DataCorruptedException
|
||||
public static FullDataSourceV2 createFromApiChunkData(DhApiChunk dataPoints) throws ClassCastException, DataCorruptedException
|
||||
{
|
||||
// get the section position
|
||||
int sectionPosX = getXOrZSectionPosFromChunkPos(apiChunk.chunkPosX);
|
||||
int sectionPosZ = getXOrZSectionPosFromChunkPos(apiChunk.chunkPosZ);
|
||||
long pos = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ);
|
||||
|
||||
// chunk relative block position in the data source
|
||||
int relSourceBlockX = Math.floorMod(apiChunk.chunkPosX, 4) * LodUtil.CHUNK_WIDTH;
|
||||
int relSourceBlockZ = Math.floorMod(apiChunk.chunkPosZ, 4) * LodUtil.CHUNK_WIDTH;
|
||||
|
||||
FullDataSourceV2 dataSource = FullDataSourceV2.createEmpty(pos);
|
||||
for (int relBlockZ = 0; relBlockZ < LodUtil.CHUNK_WIDTH; relBlockZ++)
|
||||
FullDataSourceV2 accessor = FullDataSourceV2.createEmpty(DhSectionPos.encode(new DhChunkPos(dataPoints.chunkPosX, dataPoints.chunkPosZ)));
|
||||
for (int relZ = 0; relZ < LodUtil.CHUNK_WIDTH; relZ++)
|
||||
{
|
||||
for (int relBlockX = 0; relBlockX < LodUtil.CHUNK_WIDTH; relBlockX++)
|
||||
for (int relX = 0; relX < LodUtil.CHUNK_WIDTH; relX++)
|
||||
{
|
||||
List<DhApiTerrainDataPoint> columnDataPoints = apiChunk.getDataPoints(relBlockX, relBlockZ);
|
||||
List<DhApiTerrainDataPoint> columnDataPoints = dataPoints.getDataPoints(relX, relZ);
|
||||
|
||||
|
||||
// this null check does 2 nice things at the same time:
|
||||
@@ -325,7 +322,7 @@ public class LodDataBuilder
|
||||
{
|
||||
DhApiTerrainDataPoint dataPoint = columnDataPoints.get(index);
|
||||
|
||||
int id = dataSource.mapping.addIfNotPresentAndGetId(
|
||||
int id = accessor.mapping.addIfNotPresentAndGetId(
|
||||
(IBiomeWrapper) (dataPoint.biomeWrapper),
|
||||
(IBlockStateWrapper) (dataPoint.blockStateWrapper)
|
||||
);
|
||||
@@ -333,7 +330,7 @@ public class LodDataBuilder
|
||||
packedDataPoints.set(index, FullDataPointUtil.encode(
|
||||
id,
|
||||
dataPoint.topYBlockPos - dataPoint.bottomYBlockPos,
|
||||
dataPoint.bottomYBlockPos - apiChunk.bottomYBlockPos,
|
||||
dataPoint.bottomYBlockPos - dataPoints.topYBlockPos,
|
||||
(byte) (dataPoint.blockLightLevel),
|
||||
(byte) (dataPoint.skyLightLevel)
|
||||
));
|
||||
@@ -341,14 +338,11 @@ public class LodDataBuilder
|
||||
|
||||
// TODO add the ability for API users to define a different compression mode
|
||||
// or add a "unkown" compression mode
|
||||
dataSource.setSingleColumn(
|
||||
packedDataPoints,
|
||||
relBlockX + relSourceBlockX, relBlockZ + relSourceBlockZ,
|
||||
EDhApiWorldGenerationStep.LIGHT, EDhApiWorldCompressionMode.MERGE_SAME_BLOCKS);
|
||||
dataSource.isEmpty = false;
|
||||
accessor.setSingleColumn(packedDataPoints, relX, relZ, EDhApiWorldGenerationStep.LIGHT, EDhApiWorldCompressionMode.MERGE_SAME_BLOCKS);
|
||||
}
|
||||
}
|
||||
return dataSource;
|
||||
|
||||
return accessor;
|
||||
}
|
||||
|
||||
|
||||
@@ -359,13 +353,4 @@ public class LodDataBuilder
|
||||
|
||||
public static boolean canGenerateLodFromChunk(IChunkWrapper chunk) { return chunk != null && chunk.isLightCorrect(); }
|
||||
|
||||
public static int getXOrZSectionPosFromChunkPos(int chunkXOrZPos)
|
||||
{
|
||||
// get the section position
|
||||
int sectionPos = chunkXOrZPos;
|
||||
// negative positions start at -1 so the logic there is slightly different
|
||||
sectionPos = (sectionPos < 0) ? ((sectionPos + 1) / FullDataSourceV2.NUMB_OF_CHUNKS_WIDE) - 1 : (sectionPos / FullDataSourceV2.NUMB_OF_CHUNKS_WIDE);
|
||||
return sectionPos;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import java.util.Map;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3i;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Vec3i;
|
||||
|
||||
/**
|
||||
* An (almost) exact copy of Minecraft's
|
||||
|
||||
+5
-17
@@ -41,17 +41,13 @@ import java.util.*;
|
||||
*/
|
||||
public class ClientOnlySaveStructure extends AbstractSaveStructure
|
||||
{
|
||||
public static final String SERVER_DATA_FOLDER_NAME = "Distant_Horizons_server_data";
|
||||
public static final String REPLAY_SERVER_FOLDER_NAME = "REPLAY";
|
||||
public static final String INVALID_FILE_CHARACTERS_REGEX = "[\\\\/:*?\"<>|]";
|
||||
|
||||
final File folder;
|
||||
private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
private static final IMinecraftSharedWrapper MC_SHARED = SingletonInjector.INSTANCE.get(IMinecraftSharedWrapper.class);
|
||||
public static final String INVALID_FILE_CHARACTERS_REGEX = "[\\\\/:*?\"<>|]";
|
||||
|
||||
|
||||
private SubDimensionLevelMatcher subDimMatcher = null;
|
||||
private final File folder;
|
||||
private final HashMap<ILevelWrapper, File> levelWrapperToFileMap = new HashMap<>();
|
||||
SubDimensionLevelMatcher subDimMatcher = null;
|
||||
final HashMap<ILevelWrapper, File> levelWrapperToFileMap = new HashMap<>();
|
||||
|
||||
|
||||
|
||||
@@ -241,7 +237,7 @@ public class ClientOnlySaveStructure extends AbstractSaveStructure
|
||||
private static String getSaveStructureFolderPath()
|
||||
{
|
||||
String path = MC_SHARED.getInstallationDirectory().getPath() + File.separatorChar
|
||||
+ SERVER_DATA_FOLDER_NAME + File.separatorChar
|
||||
+ "Distant_Horizons_server_data" + File.separatorChar
|
||||
+ getServerFolderName();
|
||||
return path;
|
||||
}
|
||||
@@ -249,14 +245,6 @@ public class ClientOnlySaveStructure extends AbstractSaveStructure
|
||||
/** Generated from the server the client is currently connected to. */
|
||||
private static String getServerFolderName()
|
||||
{
|
||||
// if connected to a replay we won't have any server info
|
||||
// use the dedicated replay server folder
|
||||
if (MC_CLIENT.connectedToReplay())
|
||||
{
|
||||
return REPLAY_SERVER_FOLDER_NAME;
|
||||
}
|
||||
|
||||
|
||||
// parse the current server's IP
|
||||
ParsedIp parsedIp = new ParsedIp(MC_CLIENT.getCurrentServerIp());
|
||||
String serverIpCleaned = parsedIp.ip.replaceAll(INVALID_FILE_CHARACTERS_REGEX, "");
|
||||
|
||||
+2
-2
@@ -190,7 +190,7 @@ public class SubDimensionLevelMatcher implements AutoCloseable
|
||||
}
|
||||
FullDataSourceV2 newChunkSizedFullDataView = FullDataSourceV2.createFromChunk(newlyLoadedChunk);
|
||||
// convert to a data source for easier comparing
|
||||
FullDataSourceV2 newDataSource = FullDataSourceV2.createEmpty(DhSectionPos.encodeContaining(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, this.playerData.playerBlockPos));
|
||||
FullDataSourceV2 newDataSource = FullDataSourceV2.createEmpty(DhSectionPos.encode(this.playerData.playerBlockPos));
|
||||
newDataSource.update(newChunkSizedFullDataView);
|
||||
|
||||
|
||||
@@ -215,7 +215,7 @@ public class SubDimensionLevelMatcher implements AutoCloseable
|
||||
// get the data source to compare against
|
||||
try (IDhLevel tempLevel = new DhClientLevel(new ClientOnlySaveStructure(), this.currentClientLevel, testLevelFolder, false, null))
|
||||
{
|
||||
testFullDataSource = tempLevel.getFullDataProvider().getAsync(DhSectionPos.encodeContaining(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, this.playerData.playerBlockPos)).join();
|
||||
testFullDataSource = tempLevel.getFullDataProvider().getAsync(DhSectionPos.encode(this.playerData.playerBlockPos)).join();
|
||||
if (testFullDataSource == null)
|
||||
{
|
||||
continue;
|
||||
|
||||
-117
@@ -1,117 +0,0 @@
|
||||
package com.seibel.distanthorizons.core.generation;
|
||||
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.util.BitShiftUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
|
||||
/** holds adjacent chunks without having to create new Pos objects */
|
||||
public class AdjacentChunkHolder
|
||||
{
|
||||
final IChunkWrapper[] chunkArray = new IChunkWrapper[9];
|
||||
|
||||
|
||||
//==============//
|
||||
// constructors //
|
||||
//==============//
|
||||
|
||||
public AdjacentChunkHolder(IChunkWrapper centerWrapper) { this.chunkArray[4] = centerWrapper; }
|
||||
|
||||
public AdjacentChunkHolder(IChunkWrapper centerWrapper, @NotNull ArrayList<IChunkWrapper> nearbyChunkList)
|
||||
{
|
||||
this.chunkArray[4] = centerWrapper;
|
||||
|
||||
DhChunkPos centerChunkPos = centerWrapper.getChunkPos();
|
||||
|
||||
// generate the list of chunk pos we need,
|
||||
// currently a 3x3 grid
|
||||
HashSet<DhChunkPos> requestedAdjacentPositions = new HashSet<>(9);
|
||||
for (int xOffset = -1; xOffset <= 1; xOffset++)
|
||||
{
|
||||
for (int zOffset = -1; zOffset <= 1; zOffset++)
|
||||
{
|
||||
DhChunkPos adjacentPos = new DhChunkPos(centerChunkPos.x + xOffset, centerChunkPos.z + zOffset);
|
||||
requestedAdjacentPositions.add(adjacentPos);
|
||||
}
|
||||
}
|
||||
|
||||
for (int chunkIndex = 0; chunkIndex < nearbyChunkList.size(); chunkIndex++) // using iterators in high traffic areas can cause GC issues due to allocating a bunch of iterators, use an indexed for-loop instead
|
||||
{
|
||||
IChunkWrapper chunk = nearbyChunkList.get(chunkIndex);
|
||||
if (chunk != null && requestedAdjacentPositions.contains(chunk.getChunkPos()))
|
||||
{
|
||||
// remove the newly found position
|
||||
requestedAdjacentPositions.remove(chunk.getChunkPos());
|
||||
|
||||
// add the adjacent chunk
|
||||
this.add(chunk);
|
||||
}
|
||||
|
||||
if (requestedAdjacentPositions.isEmpty())
|
||||
{
|
||||
// we found every chunk we needed, we don't need to keep iterating
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// methods //
|
||||
//=========//
|
||||
|
||||
public void add(IChunkWrapper centerWrapper)
|
||||
{
|
||||
DhChunkPos centerPos = this.chunkArray[4].getChunkPos();
|
||||
DhChunkPos offsetPos = centerWrapper.getChunkPos();
|
||||
|
||||
int offsetX = offsetPos.x - centerPos.x;
|
||||
if (offsetX < -1 || offsetX > 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int offsetZ = offsetPos.z - centerPos.z;
|
||||
if (offsetZ < -1 || offsetZ > 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// equivalent to 4 + offsetX + (offsetZ * 3).
|
||||
this.chunkArray[4 + offsetX + offsetZ + (offsetZ << 1)] = centerWrapper;
|
||||
}
|
||||
|
||||
public IChunkWrapper getByBlockPos(int blockX, int blockZ)
|
||||
{
|
||||
int chunkX = BitShiftUtil.divideByPowerOfTwo(blockX, 4);
|
||||
int chunkZ = BitShiftUtil.divideByPowerOfTwo(blockZ, 4);
|
||||
IChunkWrapper centerChunk = this.chunkArray[4];
|
||||
DhChunkPos centerPos = centerChunk.getChunkPos();
|
||||
if (centerPos.x == chunkX && centerPos.z == chunkZ)
|
||||
{
|
||||
return centerChunk;
|
||||
}
|
||||
|
||||
int offsetX = chunkX - centerPos.x;
|
||||
if (offsetX < -1 || offsetX > 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int offsetZ = chunkZ - centerPos.z;
|
||||
if (offsetZ < -1 || offsetZ > 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// equivalent to 4 + offsetX + (offsetZ * 3).
|
||||
return this.chunkArray[4 + offsetX + offsetZ + (offsetZ << 1)];
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+60
-1
@@ -26,6 +26,7 @@ import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.util.BitShiftUtil;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.*;
|
||||
@@ -151,7 +152,7 @@ public class DhLightingEngine
|
||||
for (int y = maxY; y >= minY; y--)
|
||||
{
|
||||
IBlockStateWrapper block = chunk.getBlockState(relX, y, relZ);
|
||||
if (block != null && block.getOpacity() != LodUtil.BLOCK_FULLY_TRANSPARENT)
|
||||
if (block != null && block.getOpacity() != IBlockStateWrapper.FULLY_TRANSPARENT)
|
||||
{
|
||||
// keep moving down until we find a non-transparent block
|
||||
break;
|
||||
@@ -305,6 +306,64 @@ public class DhLightingEngine
|
||||
|
||||
}
|
||||
|
||||
/** holds the adjacent chunks without having to create new Pos objects */
|
||||
private static class AdjacentChunkHolder
|
||||
{
|
||||
final IChunkWrapper[] chunkArray = new IChunkWrapper[9];
|
||||
|
||||
|
||||
public AdjacentChunkHolder(IChunkWrapper centerWrapper) { this.chunkArray[4] = centerWrapper; }
|
||||
|
||||
|
||||
public void add(IChunkWrapper centerWrapper)
|
||||
{
|
||||
DhChunkPos centerPos = this.chunkArray[4].getChunkPos();
|
||||
DhChunkPos offsetPos = centerWrapper.getChunkPos();
|
||||
|
||||
int offsetX = offsetPos.x - centerPos.x;
|
||||
if (offsetX < -1 || offsetX > 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
int offsetZ = offsetPos.z - centerPos.z;
|
||||
if (offsetZ < -1 || offsetZ > 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// equivalent to 4 + offsetX + (offsetZ * 3).
|
||||
this.chunkArray[4 + offsetX + offsetZ + (offsetZ << 1)] = centerWrapper;
|
||||
}
|
||||
|
||||
public IChunkWrapper getByBlockPos(int blockX, int blockZ)
|
||||
{
|
||||
int chunkX = BitShiftUtil.divideByPowerOfTwo(blockX, 4);
|
||||
int chunkZ = BitShiftUtil.divideByPowerOfTwo(blockZ, 4);
|
||||
IChunkWrapper centerChunk = this.chunkArray[4];
|
||||
DhChunkPos centerPos = centerChunk.getChunkPos();
|
||||
if (centerPos.x == chunkX && centerPos.z == chunkZ)
|
||||
{
|
||||
return centerChunk;
|
||||
}
|
||||
|
||||
int offsetX = chunkX - centerPos.x;
|
||||
if (offsetX < -1 || offsetX > 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
int offsetZ = chunkZ - centerPos.z;
|
||||
if (offsetZ < -1 || offsetZ > 1)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// equivalent to 4 + offsetX + (offsetZ * 3).
|
||||
return this.chunkArray[4 + offsetX + offsetZ + (offsetZ << 1)];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds all potential {@link LightPos} objects a lighting task may need.
|
||||
* This is done so existing {@link LightPos} objects can be repurposed instead of destroyed,
|
||||
|
||||
+4
-7
@@ -79,7 +79,7 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb
|
||||
// TODO this logic isn't great and can cause a limit to how many threads could be used for world generation,
|
||||
// however it won't cause duplicate requests or concurrency issues, so it will be good enough for now.
|
||||
// A good long term fix may be to either:
|
||||
// 1. allow the generator to deal with larger sections (let the generator threads split up larger tasks into smaller ones
|
||||
// 1. allow the generator to deal with larger sections (let the generator threads split up larger tasks into smaller one
|
||||
// 2. batch requests better. instead of sending 4 individual tasks of detail level N, send 1 task of detail level n+1
|
||||
private final ExecutorService queueingThread = ThreadUtil.makeSingleThreadPool("World Gen Queue");
|
||||
private boolean generationQueueRunning = false;
|
||||
@@ -227,9 +227,6 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.error("queueing exception: " + e.getMessage(), e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.generationQueueRunning = false;
|
||||
}
|
||||
});
|
||||
@@ -377,7 +374,7 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb
|
||||
// don't log the shutdown exceptions
|
||||
if (!LodUtil.isInterruptOrReject(exception))
|
||||
{
|
||||
LOGGER.error("Error generating data for pos: " + DhSectionPos.toString(taskPos), exception);
|
||||
LOGGER.error("Error generating data for section " + taskPos, exception);
|
||||
}
|
||||
|
||||
newTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateFail()));
|
||||
@@ -387,11 +384,11 @@ public class WorldGenerationQueue implements IFullDataSourceRetrievalQueue, IDeb
|
||||
newTaskGroup.group.worldGenTasks.forEach(worldGenTask -> worldGenTask.future.complete(WorldGenResult.CreateSuccess(DhSectionPos.encode(granularity, DhSectionPos.getX(taskPos), DhSectionPos.getZ(taskPos)))));
|
||||
}
|
||||
boolean worked = this.inProgressGenTasksByLodPos.remove(taskPos, newTaskGroup);
|
||||
LodUtil.assertTrue(worked, "Unable to find in progress generator task with position ["+DhSectionPos.toString(taskPos)+"]");
|
||||
LodUtil.assertTrue(worked);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.error("Unexpected error completing world gen task at pos: ["+DhSectionPos.toString(taskPos)+"].", e);
|
||||
LOGGER.error("Unexpected error completing world gen task: "+taskPos, e);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -19,28 +19,15 @@
|
||||
|
||||
package com.seibel.distanthorizons.core.level;
|
||||
|
||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiChunkModifiedEvent;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
|
||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
|
||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||
import com.seibel.distanthorizons.core.dataObjects.transformers.ChunkToLodBuilder;
|
||||
import com.seibel.distanthorizons.core.file.fullDatafile.DelayedFullDataSourceSaveCache;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.BeaconRenderHandler;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.CloudRenderHandler;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericRenderObjectFactory;
|
||||
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
|
||||
import com.seibel.distanthorizons.core.sql.dto.ChunkHashDTO;
|
||||
import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo;
|
||||
import com.seibel.distanthorizons.core.sql.repo.ChunkHashRepo;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@@ -48,12 +35,8 @@ import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public abstract class AbstractDhLevel implements IDhLevel
|
||||
{
|
||||
@@ -64,37 +47,21 @@ public abstract class AbstractDhLevel implements IDhLevel
|
||||
/** if this is null then the other handler is probably null too, but just in case */
|
||||
@Nullable
|
||||
public ChunkHashRepo chunkHashRepo;
|
||||
/** if this is null then the other handler is probably null too, but just in case */
|
||||
@Nullable
|
||||
public BeaconBeamRepo beaconBeamRepo;
|
||||
|
||||
protected final DelayedFullDataSourceSaveCache delayedFullDataSourceSaveCache = new DelayedFullDataSourceSaveCache(this::onDataSourceSave, 2_000);
|
||||
/** contains the {@link DhChunkPos} for each {@link DhSectionPos} that are queued to save via {@link AbstractDhLevel#delayedFullDataSourceSaveCache} */
|
||||
protected final ConcurrentHashMap<Long, HashSet<DhChunkPos>> updatedChunkPosSetBySectionPos = new ConcurrentHashMap<>();
|
||||
|
||||
/** Will be null if clouds shouldn't be rendered for this level. */
|
||||
@Nullable
|
||||
protected CloudRenderHandler cloudRenderHandler;
|
||||
protected BeaconRenderHandler beaconRenderHandler;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
protected AbstractDhLevel()
|
||||
{
|
||||
this.chunkToLodBuilder = new ChunkToLodBuilder();
|
||||
}
|
||||
protected AbstractDhLevel() { this.chunkToLodBuilder = new ChunkToLodBuilder(); }
|
||||
|
||||
/**
|
||||
* Creating the repos requires access to the level file, which isn't
|
||||
* available at constructor time.
|
||||
*/
|
||||
protected void createAndSetSupportingRepos(File databaseFile)
|
||||
protected void createAndSetChunkHashRepo(File databaseFile)
|
||||
{
|
||||
// chunk hash
|
||||
ChunkHashRepo newChunkHashRepo = null;
|
||||
try
|
||||
{
|
||||
@@ -105,41 +72,6 @@ public abstract class AbstractDhLevel implements IDhLevel
|
||||
LOGGER.error("Unable to create [ChunkHashRepo], error: ["+e.getMessage()+"].", e);
|
||||
}
|
||||
this.chunkHashRepo = newChunkHashRepo;
|
||||
|
||||
|
||||
// beacon beam
|
||||
BeaconBeamRepo newBeaconBeamRepo = null;
|
||||
try
|
||||
{
|
||||
newBeaconBeamRepo = new BeaconBeamRepo("jdbc:sqlite", databaseFile);
|
||||
}
|
||||
catch (SQLException e)
|
||||
{
|
||||
LOGGER.error("Unable to create [BeaconBeamRepo], error: ["+e.getMessage()+"].", e);
|
||||
}
|
||||
this.beaconBeamRepo = newBeaconBeamRepo;
|
||||
}
|
||||
|
||||
/** handles any setup that needs the repos to be created */
|
||||
protected void runRepoReliantSetup()
|
||||
{
|
||||
GenericObjectRenderer genericRenderer = this.getGenericRenderer();
|
||||
if (genericRenderer != null)
|
||||
{
|
||||
// only add clouds for certain dimension types
|
||||
if (!this.getLevelWrapper().hasCeiling()
|
||||
&& !this.getLevelWrapper().getDimensionType().isTheEnd())
|
||||
{
|
||||
this.cloudRenderHandler = new CloudRenderHandler(this, genericRenderer);
|
||||
}
|
||||
|
||||
|
||||
// shouldn't happen, but just in case
|
||||
if (this.beaconBeamRepo != null)
|
||||
{
|
||||
this.beaconRenderHandler = new BeaconRenderHandler(this.beaconBeamRepo, genericRenderer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -194,13 +126,6 @@ public abstract class AbstractDhLevel implements IDhLevel
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=======//
|
||||
// repos //
|
||||
//=======//
|
||||
|
||||
// chunk hash //
|
||||
|
||||
@Override
|
||||
public int getChunkHash(DhChunkPos pos)
|
||||
{
|
||||
@@ -223,55 +148,11 @@ public abstract class AbstractDhLevel implements IDhLevel
|
||||
|
||||
|
||||
|
||||
//=================//
|
||||
// beacon handling //
|
||||
//=================//
|
||||
|
||||
@Override
|
||||
public void setBeaconBeamsForChunk(DhChunkPos chunkPos, List<BeaconBeamDTO> newBeamList)
|
||||
{
|
||||
if (this.beaconRenderHandler != null)
|
||||
{
|
||||
this.beaconRenderHandler.setBeaconBeamsForChunk(chunkPos, newBeamList);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadBeaconBeamsInPos(long pos)
|
||||
{
|
||||
if (this.beaconRenderHandler != null)
|
||||
{
|
||||
this.beaconRenderHandler.loadBeaconBeamsInPos(pos);
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void unloadBeaconBeamsInPos(long pos)
|
||||
{
|
||||
if (this.beaconRenderHandler != null)
|
||||
{
|
||||
this.beaconRenderHandler.unloadBeaconBeamsInPos(pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// base overrides //
|
||||
//================//
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
this.chunkToLodBuilder.close();
|
||||
|
||||
if (this.chunkHashRepo != null)
|
||||
{
|
||||
this.chunkHashRepo.close();
|
||||
}
|
||||
if (this.beaconBeamRepo != null)
|
||||
{
|
||||
this.beaconBeamRepo.close();
|
||||
}
|
||||
}
|
||||
public void close() { this.chunkToLodBuilder.close(); }
|
||||
|
||||
}
|
||||
@@ -27,12 +27,13 @@ import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.file.AbstractDataSourceHandler;
|
||||
import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
||||
import com.seibel.distanthorizons.core.render.LodQuadTree;
|
||||
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.LodRenderer;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
@@ -40,7 +41,9 @@ import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.annotation.WillNotClose;
|
||||
import java.io.Closeable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
public class ClientLevelModule implements Closeable, AbstractDataSourceHandler.IDataSourceUpdateFunc<FullDataSourceV2>
|
||||
@@ -53,14 +56,6 @@ public class ClientLevelModule implements Closeable, AbstractDataSourceHandler.I
|
||||
@WillNotClose
|
||||
public final FullDataSourceProviderV2 fullDataSourceProvider;
|
||||
public final AtomicReference<ClientRenderState> ClientRenderStateRef = new AtomicReference<>();
|
||||
/**
|
||||
* This is handled outside of the {@link ClientRenderState} to prevent destroying
|
||||
* the {@link GenericObjectRenderer} when changing render distances or enabling/disabling rendering. <br><br>
|
||||
*
|
||||
* Destroying the {@link GenericObjectRenderer} would cause any existing bindings to be
|
||||
* erroneously removed.
|
||||
*/
|
||||
public final GenericObjectRenderer genericRenderer = new GenericObjectRenderer();
|
||||
|
||||
|
||||
|
||||
@@ -113,7 +108,7 @@ public class ClientLevelModule implements Closeable, AbstractDataSourceHandler.I
|
||||
}
|
||||
|
||||
clientRenderState.close();
|
||||
clientRenderState = new ClientRenderState(this.clientLevel, clientLevelWrapper, this.clientLevel.getFullDataProvider(), this.genericRenderer);
|
||||
clientRenderState = new ClientRenderState(this.clientLevel, clientLevelWrapper, this.clientLevel.getFullDataProvider());
|
||||
if (!this.ClientRenderStateRef.compareAndSet(null, clientRenderState))
|
||||
{
|
||||
//FIXME: How to handle this?
|
||||
@@ -133,7 +128,7 @@ public class ClientLevelModule implements Closeable, AbstractDataSourceHandler.I
|
||||
}
|
||||
if (isBuffersDirty)
|
||||
{
|
||||
clientRenderState.lodRenderer.bufferHandler.MarkAllBuffersDirty();
|
||||
clientRenderState.renderer.bufferHandler.MarkAllBuffersDirty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -146,7 +141,7 @@ public class ClientLevelModule implements Closeable, AbstractDataSourceHandler.I
|
||||
public boolean startRenderer(IClientLevelWrapper clientLevelWrapper)
|
||||
{
|
||||
// TODO why are we passing in a level wrapper? Our client level is already defined.
|
||||
ClientRenderState ClientRenderState = new ClientRenderState(this.clientLevel, clientLevelWrapper, this.clientLevel.getFullDataProvider(), this.genericRenderer);
|
||||
ClientRenderState ClientRenderState = new ClientRenderState(this.clientLevel, clientLevelWrapper, this.clientLevel.getFullDataProvider());
|
||||
if (!this.ClientRenderStateRef.compareAndSet(null, ClientRenderState))
|
||||
{
|
||||
LOGGER.warn("Failed to start renderer due to concurrency");
|
||||
@@ -172,7 +167,7 @@ public class ClientLevelModule implements Closeable, AbstractDataSourceHandler.I
|
||||
// either the renderer hasn't been started yet, or is being reloaded
|
||||
return;
|
||||
}
|
||||
ClientRenderState.lodRenderer.drawLods(ClientRenderState.clientLevelWrapper, renderEventParam, profiler);
|
||||
ClientRenderState.renderer.drawLods(ClientRenderState.clientLevelWrapper, renderEventParam, profiler);
|
||||
}
|
||||
|
||||
public void renderDeferred(DhApiRenderParam renderEventParam, IProfilerWrapper profiler)
|
||||
@@ -183,7 +178,7 @@ public class ClientLevelModule implements Closeable, AbstractDataSourceHandler.I
|
||||
// either the renderer hasn't been started yet, or is being reloaded
|
||||
return;
|
||||
}
|
||||
ClientRenderState.lodRenderer.drawDeferredLods(ClientRenderState.clientLevelWrapper, renderEventParam, profiler);
|
||||
ClientRenderState.renderer.drawDeferredLods(ClientRenderState.clientLevelWrapper, renderEventParam, profiler);
|
||||
}
|
||||
|
||||
public void stopRenderer()
|
||||
@@ -280,25 +275,15 @@ public class ClientLevelModule implements Closeable, AbstractDataSourceHandler.I
|
||||
// helper classes //
|
||||
//================//
|
||||
|
||||
public static class ClientRenderState implements Closeable
|
||||
public static class ClientRenderState
|
||||
{
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
public final IClientLevelWrapper clientLevelWrapper;
|
||||
public final LodQuadTree quadtree;
|
||||
public final RenderBufferHandler renderBufferHandler;
|
||||
public final LodRenderer lodRenderer;
|
||||
public final LodRenderer renderer;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public ClientRenderState(
|
||||
IDhClientLevel dhClientLevel, IClientLevelWrapper clientLevelWrapper,
|
||||
FullDataSourceProviderV2 fullDataSourceProvider,
|
||||
GenericObjectRenderer genericRenderer)
|
||||
public ClientRenderState(IDhClientLevel dhClientLevel, IClientLevelWrapper clientLevelWrapper, FullDataSourceProviderV2 fullDataSourceProvider)
|
||||
{
|
||||
this.clientLevelWrapper = clientLevelWrapper;
|
||||
|
||||
@@ -307,22 +292,17 @@ public class ClientLevelModule implements Closeable, AbstractDataSourceHandler.I
|
||||
0, 0,
|
||||
fullDataSourceProvider);
|
||||
|
||||
this.renderBufferHandler = new RenderBufferHandler(this.quadtree);
|
||||
this.lodRenderer = new LodRenderer(this.renderBufferHandler, genericRenderer);
|
||||
RenderBufferHandler renderBufferHandler = new RenderBufferHandler(this.quadtree);
|
||||
this.renderer = new LodRenderer(renderBufferHandler);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// base overrides //
|
||||
//================//
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
LOGGER.info("Shutting down " + ClientRenderState.class.getSimpleName());
|
||||
|
||||
this.lodRenderer.close();
|
||||
this.renderer.close();
|
||||
this.quadtree.close();
|
||||
}
|
||||
|
||||
|
||||
@@ -34,8 +34,6 @@ import com.seibel.distanthorizons.core.multiplayer.client.FullDataRefreshQueue;
|
||||
import com.seibel.distanthorizons.core.network.event.ScopedNetworkEventSource;
|
||||
import com.seibel.distanthorizons.core.network.messages.fullData.FullDataPartialUpdateMessage;
|
||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
||||
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
||||
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
||||
import com.seibel.distanthorizons.core.sql.dto.FullDataSourceV2DTO;
|
||||
@@ -98,7 +96,6 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel
|
||||
LOGGER.warn("unable to create data folder.");
|
||||
}
|
||||
this.levelWrapper = clientLevelWrapper;
|
||||
this.levelWrapper.setParentLevel(this);
|
||||
this.saveStructure = saveStructure;
|
||||
|
||||
this.networkState = networkState;
|
||||
@@ -120,8 +117,7 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel
|
||||
|
||||
this.clientside = new ClientLevelModule(this);
|
||||
|
||||
this.createAndSetSupportingRepos(this.dataFileHandler.repo.databaseFile);
|
||||
this.runRepoReliantSetup();
|
||||
this.createAndSetChunkHashRepo(this.dataFileHandler.repo.databaseFile);
|
||||
|
||||
if (enableRendering)
|
||||
{
|
||||
@@ -302,11 +298,10 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel
|
||||
this.eventSource.close();
|
||||
}
|
||||
|
||||
this.levelWrapper.setParentLevel(null);
|
||||
this.clientside.close();
|
||||
super.close();
|
||||
this.dataFileHandler.close();
|
||||
LOGGER.info("Closed [" + DhClientLevel.class.getSimpleName() + "] for [" + this.levelWrapper + "]");
|
||||
LOGGER.info("Closed " + DhClientLevel.class.getSimpleName() + " for " + this.levelWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -319,15 +314,6 @@ public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel
|
||||
public boolean hasSkyLight() { return this.levelWrapper.hasSkyLight(); }
|
||||
|
||||
|
||||
@Override
|
||||
public GenericObjectRenderer getGenericRenderer() { return this.clientside.genericRenderer; }
|
||||
@Override
|
||||
public RenderBufferHandler getRenderBufferHandler()
|
||||
{
|
||||
ClientLevelModule.ClientRenderState renderState = this.clientside.ClientRenderStateRef.get();
|
||||
return (renderState != null) ? renderState.renderBufferHandler : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWorldGenTaskComplete(long pos)
|
||||
{
|
||||
|
||||
@@ -24,13 +24,11 @@ import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSour
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2;
|
||||
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
||||
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
||||
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
||||
import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.block.IBlockStateWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
@@ -68,11 +66,9 @@ public class DhClientServerLevel extends AbstractDhLevel implements IDhClientLev
|
||||
LOGGER.warn("unable to create data folder.");
|
||||
}
|
||||
this.serverLevelWrapper = serverLevelWrapper;
|
||||
this.serverLevelWrapper.setParentLevel(this);
|
||||
this.serverside = new ServerLevelModule(this, saveStructure);
|
||||
this.clientside = new ClientLevelModule(this);
|
||||
this.createAndSetSupportingRepos(this.serverside.fullDataFileHandler.repo.databaseFile);
|
||||
this.runRepoReliantSetup();
|
||||
this.createAndSetChunkHashRepo(this.serverside.fullDataFileHandler.repo.databaseFile);
|
||||
|
||||
LOGGER.info("Started " + DhClientServerLevel.class.getSimpleName() + " for " + serverLevelWrapper + " with saves at " + saveStructure);
|
||||
}
|
||||
@@ -106,7 +102,20 @@ public class DhClientServerLevel extends AbstractDhLevel implements IDhClientLev
|
||||
if (shouldDoWorldGen && !isWorldGenRunning)
|
||||
{
|
||||
// start world gen
|
||||
|
||||
// create a new queue
|
||||
this.serverside.worldGenModule.startWorldGen(this.serverside.fullDataFileHandler, new ServerLevelModule.WorldGenState(this));
|
||||
|
||||
// TODO I think this used to queue the world gen
|
||||
// is it still needed?
|
||||
// populate the queue based on the current rendering tree
|
||||
//ClientLevelModule.ClientRenderState renderState = this.clientside.ClientRenderStateRef.get();
|
||||
//Iterator<QuadNode<LodRenderSection>> iterator = renderState.quadtree.leafNodeIterator();
|
||||
//while (iterator.hasNext())
|
||||
//{
|
||||
// QuadNode<LodRenderSection> node = iterator.next();
|
||||
// //this.serverside.dataFileHandler.getAsync(node.sectionPos);
|
||||
//}
|
||||
}
|
||||
else if (!shouldDoWorldGen && isWorldGenRunning)
|
||||
{
|
||||
@@ -151,7 +160,7 @@ public class DhClientServerLevel extends AbstractDhLevel implements IDhClientLev
|
||||
}
|
||||
|
||||
@Override
|
||||
public IClientLevelWrapper getClientLevelWrapper() { return MC_CLIENT.getWrappedClientLevel(); }
|
||||
public IClientLevelWrapper getClientLevelWrapper() { return this.serverLevelWrapper.tryGetClientLevelWrapper(); }
|
||||
|
||||
@Override
|
||||
public void clearRenderCache()
|
||||
@@ -223,16 +232,6 @@ public class DhClientServerLevel extends AbstractDhLevel implements IDhClientLev
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public GenericObjectRenderer getGenericRenderer() { return this.clientside.genericRenderer; }
|
||||
@Override
|
||||
public RenderBufferHandler getRenderBufferHandler()
|
||||
{
|
||||
ClientLevelModule.ClientRenderState renderState = this.clientside.ClientRenderStateRef.get();
|
||||
return (renderState != null) ? renderState.renderBufferHandler : null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===============//
|
||||
// data handling //
|
||||
|
||||
@@ -40,11 +40,9 @@ import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.IServerPlayerWrapper;
|
||||
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Vec3d;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
@@ -77,10 +75,6 @@ public class DhServerLevel extends AbstractDhLevel implements IDhServerLevel
|
||||
private final ConcurrentMap<Long, DataSourceRequestGroup> requestGroupsByFutureId = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public DhServerLevel(AbstractSaveStructure saveStructure, IServerLevelWrapper serverLevelWrapper, RemotePlayerConnectionHandler remotePlayerConnectionHandler)
|
||||
{
|
||||
if (saveStructure.getFullDataFolder(serverLevelWrapper).mkdirs())
|
||||
@@ -89,8 +83,7 @@ public class DhServerLevel extends AbstractDhLevel implements IDhServerLevel
|
||||
}
|
||||
this.serverLevelWrapper = serverLevelWrapper;
|
||||
this.serverside = new ServerLevelModule(this, saveStructure);
|
||||
this.createAndSetSupportingRepos(this.serverside.fullDataFileHandler.repo.databaseFile);
|
||||
this.runRepoReliantSetup();
|
||||
this.createAndSetChunkHashRepo(this.serverside.fullDataFileHandler.repo.databaseFile);
|
||||
|
||||
LOGGER.info("Started DHLevel for {} with saves at {}", serverLevelWrapper, saveStructure);
|
||||
|
||||
@@ -252,10 +245,6 @@ public class DhServerLevel extends AbstractDhLevel implements IDhServerLevel
|
||||
this.worldGenPlayerCenteringQueue.add(serverPlayer);
|
||||
}
|
||||
|
||||
//=========//
|
||||
// methods //
|
||||
//=========//
|
||||
|
||||
public void removePlayer(IServerPlayerWrapper serverPlayer)
|
||||
{
|
||||
this.worldGenPlayerCenteringQueue.remove(serverPlayer);
|
||||
@@ -455,18 +444,6 @@ public class DhServerLevel extends AbstractDhLevel implements IDhServerLevel
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenericObjectRenderer getGenericRenderer()
|
||||
{
|
||||
// server-only levels don't support rendering
|
||||
return null;
|
||||
}
|
||||
@Override
|
||||
public RenderBufferHandler getRenderBufferHandler()
|
||||
{
|
||||
// server-only levels don't support rendering
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
//===========//
|
||||
|
||||
@@ -23,12 +23,8 @@ import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSour
|
||||
import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2;
|
||||
import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure;
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
||||
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
@@ -48,10 +44,6 @@ public interface IDhLevel extends AutoCloseable
|
||||
void setChunkHash(DhChunkPos pos, int chunkHash);
|
||||
void updateChunkAsync(IChunkWrapper chunk);
|
||||
|
||||
void loadBeaconBeamsInPos(long pos);
|
||||
void setBeaconBeamsForChunk(DhChunkPos chunkPos, List<BeaconBeamDTO> beamList);
|
||||
void unloadBeaconBeamsInPos(long pos);
|
||||
|
||||
FullDataSourceProviderV2 getFullDataProvider();
|
||||
|
||||
AbstractSaveStructure getSaveStructure();
|
||||
@@ -68,17 +60,5 @@ public interface IDhLevel extends AutoCloseable
|
||||
|
||||
void addDebugMenuStringsToList(List<String> messageList);
|
||||
|
||||
/**
|
||||
* Will return null if the renderer isn't set up yet. <br>
|
||||
* Not supported on the server-side.
|
||||
*/
|
||||
@Nullable
|
||||
GenericObjectRenderer getGenericRenderer();
|
||||
/**
|
||||
* Will return null if the renderer isn't set up yet. <br>
|
||||
* Not supported on the server-side.
|
||||
*/
|
||||
@Nullable
|
||||
RenderBufferHandler getRenderBufferHandler();
|
||||
|
||||
}
|
||||
@@ -22,13 +22,14 @@ package com.seibel.distanthorizons.core.logging.f3;
|
||||
import com.seibel.distanthorizons.core.api.internal.SharedApi;
|
||||
import com.seibel.distanthorizons.core.level.IDhLevel;
|
||||
import com.seibel.distanthorizons.core.render.RenderBufferHandler;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
||||
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
|
||||
import com.seibel.distanthorizons.core.world.AbstractDhWorld;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
@@ -41,6 +42,23 @@ public class F3Screen
|
||||
|
||||
|
||||
|
||||
//============//
|
||||
// properties //
|
||||
//============//
|
||||
|
||||
private static WeakReference<RenderBufferHandler> renderBufferHandlerRef = new WeakReference<>(null);
|
||||
public static void setRenderBufferHandler(@Nullable RenderBufferHandler renderBufferHandler)
|
||||
{
|
||||
if (renderBufferHandler != null && renderBufferHandlerRef.get() != null)
|
||||
{
|
||||
LOGGER.warn("multiple RenderBufferHandlers are active at once, the F3 menu may not be accurate.");
|
||||
}
|
||||
|
||||
renderBufferHandlerRef = new WeakReference<>(renderBufferHandler);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=================//
|
||||
// injection point //
|
||||
//=================//
|
||||
@@ -88,28 +106,23 @@ public class F3Screen
|
||||
// chunk updates
|
||||
messageList.add(SharedApi.INSTANCE.getDebugMenuString());
|
||||
messageList.add("");
|
||||
// rendering
|
||||
RenderBufferHandler renderBufferHandler = renderBufferHandlerRef.get();
|
||||
if (renderBufferHandler != null)
|
||||
{
|
||||
messageList.add(renderBufferHandler.getVboRenderDebugMenuString());
|
||||
String showPassString = renderBufferHandler.getShadowPassRenderDebugMenuString();
|
||||
if (showPassString != null)
|
||||
{
|
||||
messageList.add(showPassString);
|
||||
}
|
||||
messageList.add("");
|
||||
}
|
||||
// world / levels
|
||||
world.addDebugMenuStringsToList(messageList);
|
||||
for (IDhLevel level : levelIterator)
|
||||
{
|
||||
level.addDebugMenuStringsToList(messageList);
|
||||
// LOD rendering
|
||||
RenderBufferHandler renderBufferHandler = level.getRenderBufferHandler();
|
||||
if (renderBufferHandler != null)
|
||||
{
|
||||
messageList.add(renderBufferHandler.getVboRenderDebugMenuString());
|
||||
String showPassString = renderBufferHandler.getShadowPassRenderDebugMenuString();
|
||||
if (showPassString != null)
|
||||
{
|
||||
messageList.add(showPassString);
|
||||
}
|
||||
}
|
||||
// Generic rendering
|
||||
GenericObjectRenderer genericRenderer = level.getGenericRenderer();
|
||||
if (genericRenderer != null)
|
||||
{
|
||||
messageList.add(genericRenderer.getVboRenderDebugMenuString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,8 +19,7 @@
|
||||
|
||||
package com.seibel.distanthorizons.core.pos;
|
||||
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Vec3d;
|
||||
|
||||
public class DhChunkPos
|
||||
{
|
||||
@@ -32,10 +31,6 @@ public class DhChunkPos
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// constructors //
|
||||
//==============//
|
||||
|
||||
public DhChunkPos(int x, int z)
|
||||
{
|
||||
this.x = x;
|
||||
@@ -62,10 +57,6 @@ public class DhChunkPos
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// methods //
|
||||
//=========//
|
||||
|
||||
public DhBlockPos center() { return new DhBlockPos(8 + this.x << 4, 0, 8 + this.z << 4); }
|
||||
public DhBlockPos corner() { return new DhBlockPos(this.x << 4, 0, this.z << 4); }
|
||||
|
||||
@@ -79,17 +70,6 @@ public class DhChunkPos
|
||||
|
||||
public DhBlockPos2D getMinBlockPos() { return new DhBlockPos2D(this.x << 4, this.z << 4); }
|
||||
|
||||
public boolean contains(DhBlockPos pos)
|
||||
{
|
||||
int minBlockX = this.getMinBlockX();
|
||||
int minBlockZ = this.getMinBlockZ();
|
||||
int maxBlockX = minBlockX + LodUtil.CHUNK_WIDTH;
|
||||
int maxBlockZ = minBlockZ + LodUtil.CHUNK_WIDTH;
|
||||
|
||||
return minBlockX <= pos.x && pos.x <= maxBlockX
|
||||
&& minBlockZ <= pos.z && pos.z <= maxBlockZ;
|
||||
}
|
||||
|
||||
public long getLong() { return toLong(this.x, this.z); }
|
||||
|
||||
public double distance(DhChunkPos other)
|
||||
@@ -97,11 +77,6 @@ public class DhChunkPos
|
||||
return Math.sqrt(Math.pow(x - other.x, 2) + Math.pow(z - other.z, 2));
|
||||
}
|
||||
|
||||
|
||||
//================//
|
||||
// base overrides //
|
||||
//================//
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj)
|
||||
{
|
||||
|
||||
@@ -19,7 +19,6 @@
|
||||
|
||||
package com.seibel.distanthorizons.core.pos;
|
||||
|
||||
import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2;
|
||||
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.coreapi.util.BitShiftUtil;
|
||||
@@ -102,32 +101,21 @@ public class DhSectionPos
|
||||
return data;
|
||||
}
|
||||
|
||||
/** Returns the section pos at the requested detail level containing the given BlockPos */
|
||||
public static long encodeContaining(byte outputSectionDetailLevel, DhBlockPos pos)
|
||||
public static long encode(DhBlockPos pos) { return encodeBlockPos(pos.x, pos.z); }
|
||||
public static long encode(DhBlockPos2D pos) { return encodeBlockPos(pos.x, pos.z); }
|
||||
public static long encodeBlockPos(int blockX, int blockZ)
|
||||
{
|
||||
int sectionPosX = getXOrZSectionPosFromChunkOrBlockPos(pos.x, false);
|
||||
int sectionPosZ = getXOrZSectionPosFromChunkOrBlockPos(pos.z, false);
|
||||
long blockPos = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ);
|
||||
return convertToDetailLevel(blockPos, outputSectionDetailLevel);
|
||||
long pos = encode(LodUtil.BLOCK_DETAIL_LEVEL, blockX, blockZ);
|
||||
pos = convertToDetailLevel(pos, DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL);
|
||||
return pos;
|
||||
}
|
||||
/** Returns the section pos at the requested detail level containing the given ChunkPos */
|
||||
public static long encodeContaining(byte outputSectionDetailLevel, DhChunkPos pos)
|
||||
|
||||
public static long encode(DhChunkPos pos) { return encodeChunkPos(pos.x, pos.z); }
|
||||
public static long encodeChunkPos(int chunkX, int chunkZ)
|
||||
{
|
||||
int sectionPosX = getXOrZSectionPosFromChunkOrBlockPos(pos.x, true);
|
||||
int sectionPosZ = getXOrZSectionPosFromChunkOrBlockPos(pos.z, true);
|
||||
long blockPos = DhSectionPos.encode(DhSectionPos.SECTION_BLOCK_DETAIL_LEVEL, sectionPosX, sectionPosZ);
|
||||
return convertToDetailLevel(blockPos, outputSectionDetailLevel);
|
||||
}
|
||||
private static int getXOrZSectionPosFromChunkOrBlockPos(int chunkXOrZPos, boolean isChunkPos)
|
||||
{
|
||||
int sectionPos = chunkXOrZPos;
|
||||
int fullDataSourceWidth = isChunkPos ? FullDataSourceV2.NUMB_OF_CHUNKS_WIDE : (FullDataSourceV2.NUMB_OF_CHUNKS_WIDE * LodUtil.CHUNK_WIDTH);
|
||||
|
||||
// negative positions start at -1 so the logic there is slightly different
|
||||
sectionPos = (sectionPos < 0)
|
||||
? ((sectionPos + 1) / fullDataSourceWidth) - 1
|
||||
: (sectionPos / fullDataSourceWidth);
|
||||
return sectionPos;
|
||||
long pos = encode(LodUtil.CHUNK_DETAIL_LEVEL, chunkX, chunkZ);
|
||||
pos = convertToDetailLevel(pos, DhSectionPos.SECTION_CHUNK_DETAIL_LEVEL);
|
||||
return pos;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
package com.seibel.distanthorizons.core.render;
|
||||
|
||||
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiCullingFrustum;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
|
||||
import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IOverrideInjector;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
|
||||
import org.joml.FrustumIntersection;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Matrix4fc;
|
||||
@@ -36,12 +35,12 @@ public class DhFrustumBounds implements IDhApiCullingFrustum
|
||||
//=========//
|
||||
|
||||
@Override
|
||||
public void update(int worldMinBlockY, int worldMaxBlockY, DhApiMat4f dhWorldViewProjection)
|
||||
public void update(int worldMinBlockY, int worldMaxBlockY, Mat4f dhWorldViewProjection)
|
||||
{
|
||||
this.worldMinY = worldMinBlockY;
|
||||
this.worldMaxY = worldMaxBlockY;
|
||||
|
||||
Matrix4f worldViewProjection = new Matrix4f(Mat4f.createJomlMatrix(dhWorldViewProjection));
|
||||
Matrix4f worldViewProjection = new Matrix4f(dhWorldViewProjection.createJomlMatrix());
|
||||
this.frustum.set(worldViewProjection);
|
||||
|
||||
Matrix4fc matWorldViewProjectionInv = new Matrix4f(worldViewProjection).invert();
|
||||
|
||||
@@ -31,7 +31,6 @@ import com.seibel.distanthorizons.core.pos.DhBlockPos2D;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.render.renderer.DebugRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable;
|
||||
import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.ThreadUtil;
|
||||
import com.seibel.distanthorizons.core.util.objects.quadTree.QuadNode;
|
||||
@@ -330,10 +329,6 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
|
||||
}
|
||||
|
||||
// all child positions are loaded, disable this section and enable its children.
|
||||
if (renderSection.renderingEnabled)
|
||||
{
|
||||
this.level.unloadBeaconBeamsInPos(renderSection.pos);
|
||||
}
|
||||
renderSection.renderingEnabled = false;
|
||||
|
||||
// walk back down the tree and enable the child sections //TODO there are probably more efficient ways of doing this, but this will work for now
|
||||
@@ -388,7 +383,6 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
|
||||
if (!renderSection.renderingEnabled)
|
||||
{
|
||||
renderSection.renderingEnabled = true;
|
||||
this.level.loadBeaconBeamsInPos(renderSection.pos);
|
||||
|
||||
// delete/disable children, all of them will be a lower detail level than requested
|
||||
quadNode.deleteAllChildren((childRenderSection) ->
|
||||
|
||||
@@ -292,7 +292,7 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.warn("Unable to get render source " + DhSectionPos.toString(this.pos) + ", error: " + e.getMessage(), e);
|
||||
LOGGER.warn("Unable to get render source " + this.pos + ", error: " + e.getMessage(), e);
|
||||
this.renderSourceLoadingRefFuture = null;
|
||||
return null;
|
||||
}
|
||||
@@ -416,7 +416,6 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
|
||||
}
|
||||
|
||||
|
||||
this.level.unloadBeaconBeamsInPos(this.pos);
|
||||
|
||||
if (this.renderBuffer != null)
|
||||
{
|
||||
|
||||
@@ -2,9 +2,8 @@ package com.seibel.distanthorizons.core.render;
|
||||
|
||||
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.coreapi.interfaces.dependencyInjection.IOverrideInjector;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
|
||||
|
||||
/**
|
||||
* Dummy {@link IDhApiCullingFrustum} that allows everything through. <br>
|
||||
@@ -25,7 +24,7 @@ public class NeverCullFrustum implements IDhApiCullingFrustum, IDhApiShadowCulli
|
||||
//=========//
|
||||
|
||||
@Override
|
||||
public void update(int worldMinBlockY, int worldMaxBlockY, DhApiMat4f dhWorldViewProjection) { /* update isn't needed */ }
|
||||
public void update(int worldMinBlockY, int worldMaxBlockY, Mat4f dhWorldViewProjection) { /* update isn't needed */ }
|
||||
|
||||
@Override
|
||||
public boolean intersects(int lodBlockPosMinX, int lodBlockPosMinZ, int lodBlockWidth, int lodDetailLevel) { return true; }
|
||||
|
||||
@@ -41,9 +41,9 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRen
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IIrisAccessor;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IOverrideInjector;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Vec3f;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Matrix4fc;
|
||||
@@ -100,6 +100,9 @@ public class RenderBufferHandler implements AutoCloseable
|
||||
{
|
||||
DhApi.overrides.bind(IDhApiShadowCullingFrustum.class, new NeverCullFrustum());
|
||||
}
|
||||
|
||||
|
||||
F3Screen.setRenderBufferHandler(this);
|
||||
}
|
||||
|
||||
|
||||
@@ -244,7 +247,7 @@ public class RenderBufferHandler implements AutoCloseable
|
||||
if (enableFrustumCulling)
|
||||
{
|
||||
int worldMinY = clientLevelWrapper.getMinHeight();
|
||||
int worldHeight = clientLevelWrapper.getMaxHeight();
|
||||
int worldHeight = clientLevelWrapper.getHeight();
|
||||
|
||||
Vec3d cameraPos = MC_RENDER.getCameraExactPosition();
|
||||
|
||||
@@ -414,6 +417,8 @@ public class RenderBufferHandler implements AutoCloseable
|
||||
renderSection.close();
|
||||
}
|
||||
}
|
||||
|
||||
F3Screen.setRenderBufferHandler(null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -173,7 +173,7 @@ public class LodFogConfig
|
||||
str.append("" +
|
||||
"float getNearFogThickness(float dist) \n" +
|
||||
"{ \n" +
|
||||
" return linearFog(dist, uNearFogStart, uNearFogLength, 0.0, 1.0); \n" +
|
||||
" return linearFog(dist, nearFogStart, nearFogLength, 0.0, 1.0); \n" +
|
||||
"} \n");
|
||||
|
||||
|
||||
@@ -182,7 +182,7 @@ public class LodFogConfig
|
||||
str.append("\n" +
|
||||
"float getFarFogThickness(float dist) { return 0.0; } \n" +
|
||||
"float getHeightFogThickness(float dist) { return 0.0; } \n" +
|
||||
"float calculateFarFogDepth(float horizontal, float dist, float uNearFogStart) { return 0.0; } \n" +
|
||||
"float calculateFarFogDepth(float horizontal, float dist, float nearFogStart) { return 0.0; } \n" +
|
||||
"float calculateHeightFogDepth(float vertical, float realY) { return 0.0; } \n" +
|
||||
"float mixFogThickness(float near, float far, float height) \n" +
|
||||
"{ \n" +
|
||||
@@ -215,13 +215,13 @@ public class LodFogConfig
|
||||
"} \n");
|
||||
|
||||
|
||||
// Generate method: calculateFarFogDepth(float horizontal, float dist, float uNearFogStart);
|
||||
// Generate method: calculateFarFogDepth(float horizontal, float dist, float nearFogStart);
|
||||
str.append("" +
|
||||
"float calculateFarFogDepth(float horizontal, float dist, float uNearFogStart) \n" +
|
||||
"float calculateFarFogDepth(float horizontal, float dist, float nearFogStart) \n" +
|
||||
"{ \n" +
|
||||
" return " + (heightFogMixMode == EDhApiHeightFogMixMode.BASIC ?
|
||||
"(dist - uNearFogStart)/(1.0 - uNearFogStart);" :
|
||||
"(horizontal - uNearFogStart)/(1.0 - uNearFogStart);") +
|
||||
"(dist - nearFogStart)/(1.0 - nearFogStart);" :
|
||||
"(horizontal - nearFogStart)/(1.0 - nearFogStart);") +
|
||||
"} \n");
|
||||
|
||||
// Generate method: float mixFogThickness(float near, float far, float height);
|
||||
|
||||
@@ -27,6 +27,7 @@ import com.seibel.distanthorizons.core.logging.ConfigBasedLogger;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.util.objects.GLMessage;
|
||||
import com.seibel.distanthorizons.core.util.objects.GLMessageOutputStream;
|
||||
import com.seibel.distanthorizons.core.util.objects.Pair;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
@@ -39,6 +40,8 @@ import org.lwjgl.opengl.GLUtil;
|
||||
|
||||
import java.io.PrintStream;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.ConcurrentLinkedQueue;
|
||||
|
||||
/**
|
||||
@@ -73,9 +76,7 @@ public class GLProxy
|
||||
|
||||
public boolean namedObjectSupported = false; // ~OpenGL 4.5 (UNUSED CURRENTLY)
|
||||
public boolean bufferStorageSupported = false; // ~OpenGL 4.4
|
||||
public boolean vertexAttributeBufferBindingSupported = false; // ~OpenGL 4.3
|
||||
public boolean instancedArraysSupported = false;
|
||||
public boolean vertexAttribDivisorSupported = false; // OpenGL 3.3 or newer
|
||||
public boolean VertexAttributeBufferBindingSupported = false; // ~OpenGL 4.3
|
||||
|
||||
private final EDhApiGpuUploadMethod preferredUploadMethod;
|
||||
|
||||
@@ -90,14 +91,16 @@ public class GLProxy
|
||||
private GLProxy() throws IllegalStateException
|
||||
{
|
||||
// this must be created on minecraft's render context to work correctly
|
||||
if (GLFW.glfwGetCurrentContext() == 0L)
|
||||
{
|
||||
throw new IllegalStateException(GLProxy.class.getSimpleName() + " was created outside the render thread!");
|
||||
}
|
||||
|
||||
GL_LOGGER.info("Creating " + GLProxy.class.getSimpleName() + "... If this is the last message you see there must have been an OpenGL error.");
|
||||
GL_LOGGER.info("Lod Render OpenGL version [" + GL32.glGetString(GL32.GL_VERSION) + "].");
|
||||
|
||||
// getting Minecraft's context has to be done on the render thread,
|
||||
// where the GL context is
|
||||
if (GLFW.glfwGetCurrentContext() == 0L)
|
||||
{
|
||||
throw new IllegalStateException(GLProxy.class.getSimpleName() + " was created outside the render thread!");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -132,26 +135,21 @@ public class GLProxy
|
||||
// get GPU capabilities //
|
||||
//======================//
|
||||
|
||||
// Check if we can use the make-over version of Vertex Attribute, which is available in GL4.3 or after
|
||||
this.VertexAttributeBufferBindingSupported = this.glCapabilities.glBindVertexBuffer != 0L; // Nullptr
|
||||
|
||||
// UNUSED currently
|
||||
// Check if we can use the named version of all calls, which is available in GL4.5 or after
|
||||
this.namedObjectSupported = this.glCapabilities.glNamedBufferData != 0L; //Nullptr
|
||||
|
||||
// get specific capabilities
|
||||
// Check if we can use the Buffer Storage, which is available in GL4.4 or after
|
||||
this.bufferStorageSupported = this.glCapabilities.glBufferStorage != 0L; // Nullptr
|
||||
if (!this.bufferStorageSupported)
|
||||
{
|
||||
GL_LOGGER.info("This GPU doesn't support Buffer Storage (OpenGL 4.4), falling back to using other methods.");
|
||||
GL_LOGGER.warn("This GPU doesn't support Buffer Storage (OpenGL 4.4), falling back to using other methods.");
|
||||
}
|
||||
|
||||
// Check if we can use the make-over version of Vertex Attribute, which is available in GL4.3 or after
|
||||
this.vertexAttributeBufferBindingSupported = this.glCapabilities.glBindVertexBuffer != 0L; // Nullptr
|
||||
|
||||
// used by instanced rendering
|
||||
this.vertexAttribDivisorSupported = this.glCapabilities.OpenGL33;
|
||||
// denotes if ARBInstancedArrays.glVertexAttribDivisorARB() is available or not
|
||||
// can be used as a backup if MC didn't create a GL 3.3+ context
|
||||
this.instancedArraysSupported = this.glCapabilities.GL_ARB_instanced_arrays;
|
||||
|
||||
// get the best automatic upload method
|
||||
String vendor = GL32.glGetString(GL32.GL_VENDOR).toUpperCase(); // example return: "NVIDIA CORPORATION"
|
||||
if (vendor.contains("NVIDIA") || vendor.contains("GEFORCE"))
|
||||
|
||||
+1
-5
@@ -20,7 +20,6 @@
|
||||
package com.seibel.distanthorizons.core.render.glObject.buffer;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
@@ -141,10 +140,7 @@ public class GLBuffer implements AutoCloseable
|
||||
GL32.glDeleteBuffers(id);
|
||||
bufferCount.decrementAndGet();
|
||||
|
||||
if (Config.Client.Advanced.Debugging.logBufferGarbageCollection.get())
|
||||
{
|
||||
LOGGER.info("destroyed buffer [" + id + "], remaining: [" + BUFFER_ID_TO_PHANTOM.size() + "]");
|
||||
}
|
||||
//LOGGER.info("destroyed buffer ["+id+"], remaining: ["+BUFFER_ID_TO_PHANTOM.size()+"]");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
+7
-7
@@ -26,13 +26,12 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3i;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
import org.lwjgl.system.MemoryStack;
|
||||
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Vec3f;
|
||||
|
||||
|
||||
/**
|
||||
@@ -155,7 +154,7 @@ public class ShaderProgram
|
||||
* @return Location of the Uniform
|
||||
* @throws RuntimeException if uniform not found
|
||||
*/
|
||||
public int getUniformLocation(CharSequence name) throws RuntimeException
|
||||
public int getUniformLocation(CharSequence name)
|
||||
{
|
||||
int i = GL32.glGetUniformLocation(id, name);
|
||||
if (i == -1)
|
||||
@@ -196,10 +195,11 @@ public class ShaderProgram
|
||||
{
|
||||
GL32.glUniform3f(location, value.x, value.y, value.z);
|
||||
}
|
||||
|
||||
/** Requires ShaderProgram binded. */
|
||||
public void setUniform(int location, DhApiVec3i value)
|
||||
public void setUniform(int location, Vec3d value)
|
||||
{
|
||||
GL32.glUniform3i(location, value.x, value.y, value.z);
|
||||
GL32.glUniform3f(location, (float) value.x, (float) value.y, (float) value.z);
|
||||
}
|
||||
|
||||
/** Requires ShaderProgram binded. */
|
||||
|
||||
+1
-1
@@ -48,7 +48,7 @@ public abstract class AbstractVertexAttribute
|
||||
|
||||
public static AbstractVertexAttribute create()
|
||||
{
|
||||
if (GLProxy.getInstance().vertexAttributeBufferBindingSupported)
|
||||
if (GLProxy.getInstance().VertexAttributeBufferBindingSupported)
|
||||
{
|
||||
return new VertexAttributePostGL43();
|
||||
}
|
||||
|
||||
+77
-78
@@ -36,9 +36,9 @@ import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
|
||||
import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.AbstractVertexAttribute;
|
||||
import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexPointer;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Vec3f;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -64,13 +64,13 @@ public class DebugRenderer
|
||||
|
||||
// rendering setup
|
||||
private ShaderProgram basicShader;
|
||||
private GLVertexBuffer vertexBuffer;
|
||||
private GLElementBuffer outlineIndexBuffer;
|
||||
private GLVertexBuffer boxBuffer;
|
||||
private GLElementBuffer boxOutlineBuffer;
|
||||
private AbstractVertexAttribute va;
|
||||
private boolean init = false;
|
||||
|
||||
// used when rendering
|
||||
private Mat4f transformationMatrixThisFrame;
|
||||
private Mat4f transformThiFrame;
|
||||
private Vec3f camPosFloatThisFrame;
|
||||
|
||||
|
||||
@@ -79,8 +79,8 @@ public class DebugRenderer
|
||||
|
||||
|
||||
|
||||
/** A box from 0,0,0 to 1,1,1 */
|
||||
private static final float[] BOX_VERTICES = {
|
||||
// A box from 0,0,0 to 1,1,1
|
||||
private static final float[] box_vertices = {
|
||||
// Pos x y z
|
||||
0, 0, 0,
|
||||
1, 0, 0,
|
||||
@@ -92,7 +92,7 @@ public class DebugRenderer
|
||||
0, 1, 1,
|
||||
};
|
||||
|
||||
private static final int[] BOX_OUTLINE_INDICES = {
|
||||
private static final int[] box_outline_indices = {
|
||||
0, 1,
|
||||
1, 2,
|
||||
2, 3,
|
||||
@@ -115,47 +115,7 @@ public class DebugRenderer
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
private DebugRenderer() { }
|
||||
|
||||
public void init()
|
||||
{
|
||||
if (this.init)
|
||||
{
|
||||
return;
|
||||
}
|
||||
this.init = true;
|
||||
|
||||
this.va = AbstractVertexAttribute.create();
|
||||
this.va.bind();
|
||||
// Pos
|
||||
this.va.setVertexAttribute(0, 0, VertexPointer.addVec3Pointer(false));
|
||||
this.va.completeAndCheck(Float.BYTES * 3);
|
||||
this.basicShader = new ShaderProgram("shaders/debug/vert.vert", "shaders/debug/frag.frag",
|
||||
"fragColor", new String[]{"vPosition"});
|
||||
this.createBuffer();
|
||||
}
|
||||
|
||||
private void createBuffer()
|
||||
{
|
||||
// box vertices
|
||||
ByteBuffer boxVerticesBuffer = ByteBuffer.allocateDirect(BOX_VERTICES.length * Float.BYTES);
|
||||
boxVerticesBuffer.order(ByteOrder.nativeOrder());
|
||||
boxVerticesBuffer.asFloatBuffer().put(BOX_VERTICES);
|
||||
boxVerticesBuffer.rewind();
|
||||
this.vertexBuffer = new GLVertexBuffer(false);
|
||||
this.vertexBuffer.bind();
|
||||
this.vertexBuffer.uploadBuffer(boxVerticesBuffer, 8, EDhApiGpuUploadMethod.DATA, BOX_VERTICES.length * Float.BYTES);
|
||||
|
||||
|
||||
// outline vertex indexes
|
||||
ByteBuffer boxOutlineBuffer = ByteBuffer.allocateDirect(BOX_OUTLINE_INDICES.length * Integer.BYTES);
|
||||
boxOutlineBuffer.order(ByteOrder.nativeOrder());
|
||||
boxOutlineBuffer.asIntBuffer().put(BOX_OUTLINE_INDICES);
|
||||
boxOutlineBuffer.rewind();
|
||||
this.outlineIndexBuffer = new GLElementBuffer(false);
|
||||
this.outlineIndexBuffer.uploadBuffer(boxOutlineBuffer, EDhApiGpuUploadMethod.DATA, BOX_OUTLINE_INDICES.length * Integer.BYTES, GL32.GL_STATIC_DRAW);
|
||||
|
||||
}
|
||||
public DebugRenderer() { }
|
||||
|
||||
|
||||
|
||||
@@ -181,13 +141,53 @@ public class DebugRenderer
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
//===========//
|
||||
// rendering //
|
||||
//===========//
|
||||
|
||||
public void init()
|
||||
{
|
||||
if (this.init)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.init = true;
|
||||
this.va = AbstractVertexAttribute.create();
|
||||
this.va.bind();
|
||||
// Pos
|
||||
this.va.setVertexAttribute(0, 0, VertexPointer.addVec3Pointer(false));
|
||||
this.va.completeAndCheck(Float.BYTES * 3);
|
||||
this.basicShader = new ShaderProgram("shaders/debug/vert.vert", "shaders/debug/frag.frag",
|
||||
"fragColor", new String[]{"vPosition"});
|
||||
this.createBuffer();
|
||||
}
|
||||
|
||||
private void createBuffer()
|
||||
{
|
||||
ByteBuffer buffer = ByteBuffer.allocateDirect(box_vertices.length * Float.BYTES);
|
||||
buffer.order(ByteOrder.nativeOrder());
|
||||
buffer.asFloatBuffer().put(box_vertices);
|
||||
buffer.rewind();
|
||||
|
||||
this.boxBuffer = new GLVertexBuffer(false);
|
||||
this.boxBuffer.bind();
|
||||
this.boxBuffer.uploadBuffer(buffer, 8, EDhApiGpuUploadMethod.DATA, box_vertices.length * Float.BYTES);
|
||||
|
||||
buffer = ByteBuffer.allocateDirect(box_outline_indices.length * Integer.BYTES);
|
||||
buffer.order(ByteOrder.nativeOrder());
|
||||
buffer.asIntBuffer().put(box_outline_indices);
|
||||
buffer.rewind();
|
||||
|
||||
this.boxOutlineBuffer = new GLElementBuffer(false);
|
||||
this.boxOutlineBuffer.uploadBuffer(buffer, EDhApiGpuUploadMethod.DATA, box_outline_indices.length * Integer.BYTES, GL32.GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
public void render(Mat4f transform)
|
||||
{
|
||||
this.transformationMatrixThisFrame = transform;
|
||||
this.transformThiFrame = transform;
|
||||
Vec3d camPos = MC_RENDER.getCameraExactPosition();
|
||||
this.camPosFloatThisFrame = new Vec3f((float) camPos.x, (float) camPos.y, (float) camPos.z);
|
||||
|
||||
@@ -199,23 +199,22 @@ public class DebugRenderer
|
||||
|
||||
this.basicShader.bind();
|
||||
this.va.bind();
|
||||
this.va.bindBufferToAllBindingPoints(this.vertexBuffer.getId());
|
||||
this.va.bindBufferToAllBindingPoints(this.boxBuffer.getId());
|
||||
|
||||
this.outlineIndexBuffer.bind();
|
||||
this.boxOutlineBuffer.bind();
|
||||
|
||||
this.rendererLists.render(this);
|
||||
|
||||
|
||||
BoxParticle head = null;
|
||||
while ((head = this.particles.poll()) != null && head.isDead(System.nanoTime()))
|
||||
{ /* remove dead particles */ }
|
||||
{
|
||||
}
|
||||
if (head != null)
|
||||
{
|
||||
// re-add the popped off head
|
||||
this.particles.add(head);
|
||||
}
|
||||
|
||||
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL);
|
||||
for (BoxParticle particle : this.particles)
|
||||
{
|
||||
this.renderBox(particle.getBox());
|
||||
@@ -227,13 +226,13 @@ public class DebugRenderer
|
||||
|
||||
public void renderBox(Box box)
|
||||
{
|
||||
Mat4f boxTransform = Mat4f.createTranslateMatrix(box.minPos.x - this.camPosFloatThisFrame.x, box.minPos.y - this.camPosFloatThisFrame.y, box.minPos.z - this.camPosFloatThisFrame.z);
|
||||
boxTransform.multiply(Mat4f.createScaleMatrix(box.maxPos.x - box.minPos.x, box.maxPos.y - box.minPos.y, box.maxPos.z - box.minPos.z));
|
||||
Mat4f t = this.transformationMatrixThisFrame.copy();
|
||||
Mat4f boxTransform = Mat4f.createTranslateMatrix(box.a.x - this.camPosFloatThisFrame.x, box.a.y - this.camPosFloatThisFrame.y, box.a.z - this.camPosFloatThisFrame.z);
|
||||
boxTransform.multiply(Mat4f.createScaleMatrix(box.b.x - box.a.x, box.b.y - box.a.y, box.b.z - box.a.z));
|
||||
Mat4f t = this.transformThiFrame.copy();
|
||||
t.multiply(boxTransform);
|
||||
this.basicShader.setUniform(this.basicShader.getUniformLocation("uTransform"), t);
|
||||
this.basicShader.setUniform(this.basicShader.getUniformLocation("transform"), t);
|
||||
this.basicShader.setUniform(this.basicShader.getUniformLocation("uColor"), box.color);
|
||||
GL32.glDrawElements(GL32.GL_LINES, BOX_OUTLINE_INDICES.length, GL32.GL_UNSIGNED_INT, 0);
|
||||
GL32.glDrawElements(GL32.GL_LINES, box_outline_indices.length, GL32.GL_UNSIGNED_INT, 0);
|
||||
}
|
||||
|
||||
|
||||
@@ -244,25 +243,25 @@ public class DebugRenderer
|
||||
|
||||
public static final class Box
|
||||
{
|
||||
public Vec3f minPos;
|
||||
public Vec3f maxPos;
|
||||
public Vec3f a;
|
||||
public Vec3f b;
|
||||
public Color color;
|
||||
|
||||
|
||||
|
||||
public Box(Vec3f minPos, Vec3f maxPos, Color color)
|
||||
public Box(Vec3f a, Vec3f b, Color color)
|
||||
{
|
||||
this.minPos = minPos;
|
||||
this.maxPos = maxPos;
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
public Box(Vec3f minPos, Vec3f maxPos, Color color, Vec3f margin)
|
||||
public Box(Vec3f a, Vec3f b, Color color, Vec3f margin)
|
||||
{
|
||||
this.minPos = minPos;
|
||||
this.minPos.add(margin);
|
||||
this.maxPos = maxPos;
|
||||
this.maxPos.subtract(margin);
|
||||
this.a = a;
|
||||
this.a.add(margin);
|
||||
this.b = b;
|
||||
this.b.subtract(margin);
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
@@ -273,8 +272,8 @@ public class DebugRenderer
|
||||
float edge = pos.getBlockWidth() * marginPercent;
|
||||
Vec3f a = new Vec3f(blockMin.x + edge, minY, blockMin.z + edge);
|
||||
Vec3f b = new Vec3f(blockMax.x - edge, maxY, blockMax.z - edge);
|
||||
this.minPos = a;
|
||||
this.maxPos = b;
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
@@ -286,8 +285,8 @@ public class DebugRenderer
|
||||
float edge = pos.getBlockWidth() * marginPercent;
|
||||
Vec3f a = new Vec3f(blockMin.x + edge, hashY, blockMin.z + edge);
|
||||
Vec3f b = new Vec3f(blockMax.x - edge, hashY, blockMax.z - edge);
|
||||
this.minPos = a;
|
||||
this.maxPos = b;
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
@@ -335,7 +334,7 @@ public class DebugRenderer
|
||||
float percent = (now - this.startTime) / (float) this.duration;
|
||||
percent = (float) Math.pow(percent, 4);
|
||||
float yDiff = this.yChange * percent;
|
||||
return new Box(new Vec3f(this.box.minPos.x, this.box.minPos.y + yDiff, this.box.minPos.z), new Vec3f(this.box.maxPos.x, this.box.maxPos.y + yDiff, this.box.maxPos.z), this.box.color);
|
||||
return new Box(new Vec3f(this.box.a.x, this.box.a.y + yDiff, this.box.a.z), new Vec3f(this.box.b.x, this.box.b.y + yDiff, this.box.b.z), this.box.color);
|
||||
}
|
||||
|
||||
public boolean isDead(long time) { return (time - this.startTime) > this.duration; }
|
||||
@@ -351,7 +350,7 @@ public class DebugRenderer
|
||||
public BoxWithLife(Box box, long ns, float yChange, Color deathColor)
|
||||
{
|
||||
this.box = box;
|
||||
this.particaleOnClose = new BoxParticle(new Box(box.minPos, box.maxPos, deathColor), -1, ns, yChange);
|
||||
this.particaleOnClose = new BoxParticle(new Box(box.a, box.b, deathColor), -1, ns, yChange);
|
||||
register(this, null);
|
||||
}
|
||||
|
||||
@@ -361,7 +360,7 @@ public class DebugRenderer
|
||||
public BoxWithLife(Box box, double s, float yChange, Color deathColor)
|
||||
{
|
||||
this.box = box;
|
||||
this.particaleOnClose = new BoxParticle(new Box(box.minPos, box.maxPos, deathColor), s, yChange);
|
||||
this.particaleOnClose = new BoxParticle(new Box(box.a, box.b, deathColor), s, yChange);
|
||||
}
|
||||
|
||||
public BoxWithLife(Box box, double s, float yChange) { this(box, s, yChange, box.color); }
|
||||
|
||||
@@ -1,135 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2023 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.core.render.renderer;
|
||||
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLState;
|
||||
import com.seibel.distanthorizons.core.render.renderer.shaders.FogApplyShader;
|
||||
import com.seibel.distanthorizons.core.render.renderer.shaders.FogShader;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* Handles adding SSAO via {@link FogShader} and {@link FogApplyShader}. <br><br>
|
||||
*
|
||||
* {@link FogShader} - draws the Fog to a texture. <br>
|
||||
* {@link FogApplyShader} - draws the Fog texture to DH's FrameBuffer. <br>
|
||||
*/
|
||||
public class FogRenderer
|
||||
{
|
||||
public static FogRenderer INSTANCE = new FogRenderer();
|
||||
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
|
||||
|
||||
private boolean init = false;
|
||||
|
||||
private int width = -1;
|
||||
private int height = -1;
|
||||
private int fogFramebuffer = -1;
|
||||
|
||||
private int fogTexture = -1;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
private FogRenderer() { }
|
||||
|
||||
public void init()
|
||||
{
|
||||
if (this.init) return;
|
||||
this.init = true;
|
||||
|
||||
FogShader.INSTANCE.init();
|
||||
FogApplyShader.INSTANCE.init();
|
||||
}
|
||||
|
||||
private void createFramebuffer(int width, int height)
|
||||
{
|
||||
if (this.fogFramebuffer != -1)
|
||||
{
|
||||
GL32.glDeleteFramebuffers(this.fogFramebuffer);
|
||||
this.fogFramebuffer = -1;
|
||||
}
|
||||
|
||||
if (this.fogTexture != -1)
|
||||
{
|
||||
GL32.glDeleteTextures(this.fogTexture);
|
||||
this.fogTexture = -1;
|
||||
}
|
||||
|
||||
this.fogFramebuffer = GL32.glGenFramebuffers();
|
||||
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, this.fogFramebuffer);
|
||||
|
||||
this.fogTexture = GL32.glGenTextures();
|
||||
GL32.glBindTexture(GL32.GL_TEXTURE_2D, this.fogTexture);
|
||||
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_RGBA16, width, height, 0, GL32.GL_RGBA, GL32.GL_UNSIGNED_SHORT_4_4_4_4, (ByteBuffer) null);
|
||||
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_LINEAR);
|
||||
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MAG_FILTER, GL32.GL_LINEAR);
|
||||
GL32.glFramebufferTexture2D(GL32.GL_FRAMEBUFFER, GL32.GL_COLOR_ATTACHMENT0, GL32.GL_TEXTURE_2D, this.fogTexture, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//========//
|
||||
// render //
|
||||
//========//
|
||||
|
||||
public void render(GLState primaryState, Mat4f projectionMatrix, float partialTicks)
|
||||
{
|
||||
GLState state = new GLState();
|
||||
this.init();
|
||||
|
||||
// resize the framebuffer if necessary
|
||||
int width = MC_RENDER.getTargetFrameBufferViewportWidth();
|
||||
int height = MC_RENDER.getTargetFrameBufferViewportHeight();
|
||||
if (this.width != width || this.height != height)
|
||||
{
|
||||
this.width = width;
|
||||
this.height = height;
|
||||
this.createFramebuffer(width, height);
|
||||
}
|
||||
|
||||
FogShader.INSTANCE.frameBuffer = this.fogFramebuffer;
|
||||
FogShader.INSTANCE.setProjectionMatrix(projectionMatrix);
|
||||
FogShader.INSTANCE.render(partialTicks);
|
||||
|
||||
// restored so we can write the SSAO texture to the main frame buffer
|
||||
primaryState.restore();
|
||||
|
||||
FogApplyShader.INSTANCE.fogTexture = this.fogTexture;
|
||||
FogApplyShader.INSTANCE.render(partialTicks);
|
||||
|
||||
state.restore();
|
||||
}
|
||||
|
||||
public void free()
|
||||
{
|
||||
FogShader.INSTANCE.free();
|
||||
FogApplyShader.INSTANCE.free();
|
||||
}
|
||||
|
||||
}
|
||||
+59
-64
@@ -21,7 +21,6 @@ package com.seibel.distanthorizons.core.render.renderer;
|
||||
|
||||
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShaderProgram;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
||||
import com.seibel.distanthorizons.core.render.glObject.shader.Shader;
|
||||
@@ -32,38 +31,39 @@ import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexAtt
|
||||
import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexPointer;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.RenderUtil;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Vec3f;
|
||||
|
||||
/**
|
||||
* Handles rendering the normal LOD terrain.
|
||||
*/
|
||||
public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShaderProgram
|
||||
public class LodRenderProgram extends ShaderProgram implements IDhApiShaderProgram
|
||||
{
|
||||
public static final String VERTEX_SHADER_PATH = "shaders/standard.vert";
|
||||
public static final String VERTEX_CURVE_SHADER_PATH = "shaders/curve.vert";
|
||||
public static final String FRAGMENT_SHADER_PATH = "shaders/flat_shaded.frag";
|
||||
|
||||
public final AbstractVertexAttribute vao;
|
||||
|
||||
// Uniforms
|
||||
public final int uCombinedMatrix;
|
||||
public final int uModelOffset;
|
||||
public final int uWorldYOffset;
|
||||
public final int combinedMatUniform;
|
||||
public final int modelOffsetUniform;
|
||||
public final int worldYOffsetUniform;
|
||||
|
||||
public final int uMircoOffset;
|
||||
public final int mircoOffsetUniform;
|
||||
|
||||
public final int uEarthRadius;
|
||||
public final int earthRadiusUniform;
|
||||
|
||||
public final int uLightMap;
|
||||
public final int lightMapUniform;
|
||||
|
||||
// Fog/Clip Uniforms
|
||||
public final int uClipDistance;
|
||||
public final int clipDistanceUniform;
|
||||
|
||||
// Noise Uniforms
|
||||
public final int uNoiseEnabled;
|
||||
public final int uNoiseSteps;
|
||||
public final int uNoiseIntensity;
|
||||
public final int uNoiseDropoff;
|
||||
public final int noiseEnabledUniform;
|
||||
public final int noiseStepsUniform;
|
||||
public final int noiseIntensityUniform;
|
||||
public final int noiseDropoffUniform;
|
||||
|
||||
// Debug Uniform
|
||||
public final int uWhiteWorld;
|
||||
public final int whiteWorldUniform;
|
||||
|
||||
|
||||
|
||||
@@ -72,57 +72,50 @@ public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShade
|
||||
//=============//
|
||||
|
||||
// This will bind AbstractVertexAttribute
|
||||
public DhTerrainShaderProgram()
|
||||
public LodRenderProgram()
|
||||
{
|
||||
super(
|
||||
() -> Shader.loadFile(Config.Client.Advanced.Graphics.AdvancedGraphics.earthCurveRatio.get() != 0
|
||||
? "shaders/curve.vert"
|
||||
: "shaders/standard.vert",
|
||||
super(() -> Shader.loadFile(Config.Client.Advanced.Graphics.AdvancedGraphics.earthCurveRatio.get() != 0 ? VERTEX_CURVE_SHADER_PATH : VERTEX_SHADER_PATH,
|
||||
false, new StringBuilder()).toString(),
|
||||
() -> Shader.loadFile("shaders/flat_shaded.frag", false, new StringBuilder()).toString(),
|
||||
() -> Shader.loadFile(FRAGMENT_SHADER_PATH, false, new StringBuilder()).toString(),
|
||||
"fragColor", new String[]{"vPosition", "color"});
|
||||
|
||||
this.uCombinedMatrix = this.getUniformLocation("uCombinedMatrix");
|
||||
this.uModelOffset = this.getUniformLocation("uModelOffset");
|
||||
this.uWorldYOffset = this.tryGetUniformLocation("uWorldYOffset");
|
||||
this.uMircoOffset = this.getUniformLocation("uMircoOffset");
|
||||
this.uEarthRadius = this.tryGetUniformLocation("uEarthRadius");
|
||||
combinedMatUniform = getUniformLocation("combinedMatrix");
|
||||
modelOffsetUniform = getUniformLocation("modelOffset");
|
||||
worldYOffsetUniform = tryGetUniformLocation("worldYOffset");
|
||||
mircoOffsetUniform = getUniformLocation("mircoOffset");
|
||||
earthRadiusUniform = tryGetUniformLocation("earthRadius");
|
||||
|
||||
this.uLightMap = this.getUniformLocation("uLightMap");
|
||||
lightMapUniform = getUniformLocation("lightMap");
|
||||
|
||||
// Fog/Clip Uniforms
|
||||
this.uClipDistance = this.getUniformLocation("uClipDistance");
|
||||
clipDistanceUniform = getUniformLocation("clipDistance");
|
||||
|
||||
// Noise Uniforms
|
||||
this.uNoiseEnabled = this.getUniformLocation("uNoiseEnabled");
|
||||
this.uNoiseSteps = this.getUniformLocation("uNoiseSteps");
|
||||
this.uNoiseIntensity = this.getUniformLocation("uNoiseIntensity");
|
||||
this.uNoiseDropoff = this.getUniformLocation("uNoiseDropoff");
|
||||
noiseEnabledUniform = getUniformLocation("noiseEnabled");
|
||||
noiseStepsUniform = getUniformLocation("noiseSteps");
|
||||
noiseIntensityUniform = getUniformLocation("noiseIntensity");
|
||||
noiseDropoffUniform = getUniformLocation("noiseDropoff");
|
||||
|
||||
// Debug Uniform
|
||||
this.uWhiteWorld = this.getUniformLocation("uWhiteWorld");
|
||||
whiteWorldUniform = getUniformLocation("whiteWorld");
|
||||
|
||||
|
||||
// TODO: Add better use of the LODFormat thing
|
||||
int vertexByteCount = LodUtil.LOD_VERTEX_FORMAT.getByteSize();
|
||||
if (GLProxy.getInstance().vertexAttributeBufferBindingSupported)
|
||||
{
|
||||
this.vao = new VertexAttributePostGL43(); // also binds AbstractVertexAttribute
|
||||
}
|
||||
if (GLProxy.getInstance().VertexAttributeBufferBindingSupported)
|
||||
vao = new VertexAttributePostGL43(); // also binds AbstractVertexAttribute
|
||||
else
|
||||
{
|
||||
this.vao = new VertexAttributePreGL43(); // also binds AbstractVertexAttribute
|
||||
}
|
||||
this.vao.bind();
|
||||
vao = new VertexAttributePreGL43(); // also binds AbstractVertexAttribute
|
||||
vao.bind();
|
||||
|
||||
// TODO comment what each attribute represents
|
||||
this.vao.setVertexAttribute(0, 0, VertexPointer.addUnsignedShortsPointer(4, false, true)); // 2+2+2+2 // TODO probably color, blockpos
|
||||
this.vao.setVertexAttribute(0, 1, VertexPointer.addUnsignedBytesPointer(4, true, false)); // +4 // TODO ?
|
||||
this.vao.setVertexAttribute(0, 2, VertexPointer.addUnsignedBytesPointer(4, true, true)); // +4 // TODO probably normal index and Iris block ID
|
||||
vao.setVertexAttribute(0, 0, VertexPointer.addUnsignedShortsPointer(4, false, true)); // 2+2+2+2 // TODO probably color, blockpos
|
||||
vao.setVertexAttribute(0, 1, VertexPointer.addUnsignedBytesPointer(4, true, false)); // +4 // TODO ?
|
||||
vao.setVertexAttribute(0, 2, VertexPointer.addUnsignedBytesPointer(4, true, true)); // +4 // TODO probably normal index and Iris block ID
|
||||
|
||||
try
|
||||
{
|
||||
this.vao.completeAndCheck(vertexByteCount);
|
||||
vao.completeAndCheck(vertexByteCount);
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
@@ -130,15 +123,15 @@ public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShade
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (this.uEarthRadius != -1) this.setUniform(this.uEarthRadius,
|
||||
if (earthRadiusUniform != -1) setUniform(earthRadiusUniform,
|
||||
/*6371KM*/ 6371000.0f / Config.Client.Advanced.Graphics.AdvancedGraphics.earthCurveRatio.get());
|
||||
|
||||
|
||||
// Noise Uniforms
|
||||
this.setUniform(this.uNoiseEnabled, Config.Client.Advanced.Graphics.NoiseTextureSettings.noiseEnabled.get());
|
||||
this.setUniform(this.uNoiseSteps, Config.Client.Advanced.Graphics.NoiseTextureSettings.noiseSteps.get());
|
||||
this.setUniform(this.uNoiseIntensity, Config.Client.Advanced.Graphics.NoiseTextureSettings.noiseIntensity.get().floatValue());
|
||||
this.setUniform(this.uNoiseDropoff, Config.Client.Advanced.Graphics.NoiseTextureSettings.noiseDropoff.get());
|
||||
setUniform(noiseEnabledUniform, Config.Client.Advanced.Graphics.NoiseTextureSettings.noiseEnabled.get());
|
||||
setUniform(noiseStepsUniform, Config.Client.Advanced.Graphics.NoiseTextureSettings.noiseSteps.get());
|
||||
setUniform(noiseIntensityUniform, Config.Client.Advanced.Graphics.NoiseTextureSettings.noiseIntensity.get().floatValue());
|
||||
setUniform(noiseDropoffUniform, Config.Client.Advanced.Graphics.NoiseTextureSettings.noiseDropoff.get());
|
||||
}
|
||||
|
||||
|
||||
@@ -151,25 +144,27 @@ public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShade
|
||||
public void bind()
|
||||
{
|
||||
super.bind();
|
||||
this.vao.bind();
|
||||
vao.bind();
|
||||
}
|
||||
@Override
|
||||
public void unbind()
|
||||
{
|
||||
super.unbind();
|
||||
this.vao.unbind();
|
||||
vao.unbind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void free()
|
||||
{
|
||||
this.vao.free();
|
||||
vao.free();
|
||||
super.free();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindVertexBuffer(int vbo) { this.vao.bindBufferToAllBindingPoints(vbo); }
|
||||
|
||||
public void unbindVertexBuffer() { this.vao.unbindBuffersFromAllBindingPoint(); }
|
||||
|
||||
@Override
|
||||
public void fillUniformData(DhApiRenderParam renderParameters)
|
||||
{
|
||||
@@ -179,16 +174,16 @@ public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShade
|
||||
super.bind();
|
||||
|
||||
// uniforms
|
||||
this.setUniform(this.uCombinedMatrix, combinedMatrix);
|
||||
this.setUniform(this.uMircoOffset, 0.01f); // 0.01 block offset
|
||||
setUniform(combinedMatUniform, combinedMatrix);
|
||||
setUniform(mircoOffsetUniform, 0.01f); // 0.01 block offset
|
||||
|
||||
// setUniform(skyLightUniform, skyLight);
|
||||
this.setUniform(this.uLightMap, 0); // TODO this should probably be passed in
|
||||
setUniform(lightMapUniform, 0); // TODO this should probably be passed in
|
||||
|
||||
if (this.uWorldYOffset != -1) this.setUniform(this.uWorldYOffset, (float) renderParameters.worldYOffset);
|
||||
if (worldYOffsetUniform != -1) setUniform(worldYOffsetUniform, (float) renderParameters.worldYOffset);
|
||||
|
||||
// Debug
|
||||
this.setUniform(this.uWhiteWorld, Config.Client.Advanced.Debugging.enableWhiteWorld.get());
|
||||
setUniform(whiteWorldUniform, Config.Client.Advanced.Debugging.enableWhiteWorld.get());
|
||||
|
||||
// Clip Uniform
|
||||
float dhNearClipDistance = RenderUtil.getNearClipPlaneDistanceInBlocks(renderParameters.partialTicks);
|
||||
@@ -202,11 +197,11 @@ public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShade
|
||||
{
|
||||
dhNearClipDistance = 1.0f;
|
||||
}
|
||||
this.setUniform(this.uClipDistance, dhNearClipDistance);
|
||||
this.setUniform(this.clipDistanceUniform, dhNearClipDistance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setModelOffsetPos(DhApiVec3f modelOffsetPos) { this.setUniform(this.uModelOffset, new Vec3f(modelOffsetPos)); }
|
||||
public void setModelOffsetPos(Vec3f modelOffsetPos) { this.setUniform(this.modelOffsetUniform, modelOffsetPos); }
|
||||
|
||||
@Override
|
||||
public int getId() { return this.id; }
|
||||
+102
-129
@@ -38,7 +38,6 @@ import com.seibel.distanthorizons.core.render.glObject.GLState;
|
||||
import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer;
|
||||
import com.seibel.distanthorizons.core.render.glObject.buffer.QuadElementBuffer;
|
||||
import com.seibel.distanthorizons.core.render.glObject.texture.*;
|
||||
import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer;
|
||||
import com.seibel.distanthorizons.core.render.renderer.shaders.*;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
@@ -51,13 +50,16 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IIrisAccess
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
|
||||
import com.seibel.distanthorizons.coreapi.DependencyInjection.OverrideInjector;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Vec3f;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.File;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
@@ -95,14 +97,90 @@ public class LodRenderer
|
||||
private int cachedWidth;
|
||||
private int cachedHeight;
|
||||
|
||||
|
||||
/** called by each {@link ColumnRenderBuffer} before rendering */
|
||||
public void setModelViewMatrixOffset(DhBlockPos pos, DhApiRenderParam renderEventParam) throws IllegalStateException
|
||||
{
|
||||
Vec3d cam = MC_RENDER.getCameraExactPosition();
|
||||
Vec3f modelPos = new Vec3f((float) (pos.x - cam.x), (float) (pos.y - cam.y), (float) (pos.z - cam.z));
|
||||
|
||||
|
||||
IDhApiShaderProgram shaderProgram = this.lodRenderProgram;
|
||||
IDhApiShaderProgram shaderProgramOverride = OverrideInjector.INSTANCE.get(IDhApiShaderProgram.class);
|
||||
if (shaderProgramOverride != null && shaderProgram.overrideThisFrame())
|
||||
{
|
||||
shaderProgram = shaderProgramOverride;
|
||||
}
|
||||
|
||||
if (!GL32.glIsProgram(shaderProgram.getId()))
|
||||
{
|
||||
throw new IllegalStateException("No GL program exists with the ID: [" + shaderProgram.getId() + "]. This either means a shader program was freed while it was still in use or was never created.");
|
||||
}
|
||||
|
||||
shaderProgram.bind();
|
||||
shaderProgram.setModelOffsetPos(modelPos);
|
||||
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeBufferRenderEvent.class, new DhApiBeforeBufferRenderEvent.EventParam(renderEventParam, modelPos));
|
||||
}
|
||||
|
||||
public void drawVbo(GLVertexBuffer vbo)
|
||||
{
|
||||
//// can be uncommented to add additional debug validation to prevent crashes if invalid buffers are being created
|
||||
//// shouldn't be used in production due to the performance hit
|
||||
//if (GL32.glIsBuffer(vbo.getId()))
|
||||
{
|
||||
IDhApiShaderProgram shaderProgram = this.lodRenderProgram;
|
||||
IDhApiShaderProgram shaderProgramOverride = OverrideInjector.INSTANCE.get(IDhApiShaderProgram.class);
|
||||
if (shaderProgramOverride != null && shaderProgram.overrideThisFrame())
|
||||
{
|
||||
shaderProgram = shaderProgramOverride;
|
||||
}
|
||||
|
||||
|
||||
vbo.bind();
|
||||
shaderProgram.bindVertexBuffer(vbo.getId());
|
||||
GL32.glDrawElements(GL32.GL_TRIANGLES, (vbo.getVertexCount() / 4) * 6, // TODO what does the 4 and 6 here represent?
|
||||
this.quadIBO.getType(), 0);
|
||||
vbo.unbind();
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// // will spam the log if uncommented, but helpful for validation
|
||||
// //LOGGER.warn("Unable to draw VBO: "+vbo.getId());
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
public static class LagSpikeCatcher
|
||||
{
|
||||
long timer = System.nanoTime();
|
||||
|
||||
public LagSpikeCatcher() { }
|
||||
|
||||
public void end(String source)
|
||||
{
|
||||
if (!ENABLE_DRAW_LAG_SPIKE_LOGGING)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.timer = System.nanoTime() - this.timer;
|
||||
if (this.timer > DRAW_LAG_SPIKE_THRESHOLD_NS)
|
||||
{
|
||||
//4 ms
|
||||
EVENT_LOGGER.debug("NOTE: " + source + " took " + Duration.ofNanos(this.timer) + "!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
|
||||
private final ReentrantLock setupLock = new ReentrantLock();
|
||||
|
||||
public final RenderBufferHandler bufferHandler;
|
||||
public final GenericObjectRenderer genericObjectRenderer;
|
||||
|
||||
|
||||
// The shader program
|
||||
IDhApiShaderProgram lodRenderProgram = null;
|
||||
@@ -127,10 +205,9 @@ public class LodRenderer
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public LodRenderer(RenderBufferHandler bufferHandler, GenericObjectRenderer genericObjectRenderer)
|
||||
public LodRenderer(RenderBufferHandler bufferHandler)
|
||||
{
|
||||
this.bufferHandler = bufferHandler;
|
||||
this.genericObjectRenderer = genericObjectRenderer;
|
||||
}
|
||||
|
||||
private boolean rendererClosed = false;
|
||||
@@ -297,41 +374,16 @@ public class LodRenderer
|
||||
// Disable blending for opaque rendering
|
||||
GL32.glDisable(GL32.GL_BLEND);
|
||||
|
||||
|
||||
// terrain
|
||||
profiler.popPush("LOD Opaque");
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeRenderPassEvent.class, renderEventParam);
|
||||
|
||||
// TODO: Directional culling
|
||||
this.bufferHandler.renderOpaque(this, renderEventParam);
|
||||
|
||||
// custom objects with SSAO
|
||||
if (Config.Client.Advanced.Graphics.GenericRendering.enableRendering.get())
|
||||
{
|
||||
profiler.popPush("Custom Objects");
|
||||
this.genericObjectRenderer.render(renderEventParam, profiler, true);
|
||||
}
|
||||
|
||||
|
||||
// SSAO
|
||||
if (Config.Client.Advanced.Graphics.Ssao.enabled.get())
|
||||
{
|
||||
profiler.popPush("LOD SSAO");
|
||||
SSAORenderer.INSTANCE.render(minecraftGlState, new Mat4f(renderEventParam.dhProjectionMatrix), renderEventParam.partialTicks);
|
||||
}
|
||||
|
||||
|
||||
// custom objects without SSAO
|
||||
if (Config.Client.Advanced.Graphics.GenericRendering.enableRendering.get())
|
||||
{
|
||||
profiler.popPush("Custom Objects");
|
||||
this.genericObjectRenderer.render(renderEventParam, profiler, false);
|
||||
}
|
||||
|
||||
|
||||
//DarkShader.INSTANCE.render(partialTicks); // A test shader to make the world darker
|
||||
|
||||
if (!deferTransparentRendering && Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled)
|
||||
{
|
||||
this.renderTransparentBuffers(profiler, renderEventParam, renderEventParam.partialTicks);
|
||||
SSAORenderer.INSTANCE.render(minecraftGlState, renderEventParam.dhProjectionMatrix, renderEventParam.partialTicks);
|
||||
}
|
||||
|
||||
|
||||
@@ -342,9 +394,16 @@ public class LodRenderer
|
||||
Mat4f combinedMatrix = new Mat4f(renderEventParam.dhProjectionMatrix);
|
||||
combinedMatrix.multiply(renderEventParam.dhModelViewMatrix);
|
||||
|
||||
FogRenderer.INSTANCE.render(minecraftGlState, combinedMatrix, renderEventParam.partialTicks);
|
||||
FogShader.INSTANCE.setModelViewProjectionMatrix(combinedMatrix);
|
||||
FogShader.INSTANCE.render(renderEventParam.partialTicks);
|
||||
}
|
||||
|
||||
//DarkShader.INSTANCE.render(partialTicks); // A test shader to make the world darker
|
||||
|
||||
if (!deferTransparentRendering && Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled)
|
||||
{
|
||||
this.renderTransparentBuffers(profiler, renderEventParam, renderEventParam.partialTicks);
|
||||
}
|
||||
|
||||
drawLagSpikeCatcher.end("LodDraw");
|
||||
|
||||
@@ -363,10 +422,9 @@ public class LodRenderer
|
||||
|
||||
// Note: this can be very slow if a lot of boxes are being rendered
|
||||
DebugRenderer.INSTANCE.render(combinedMatrix);
|
||||
profiler.popPush("LOD cleanup");
|
||||
}
|
||||
|
||||
profiler.popPush("LOD cleanup");
|
||||
|
||||
|
||||
|
||||
if (this.usingMcFrameBuffer)
|
||||
@@ -404,17 +462,6 @@ public class LodRenderer
|
||||
if (Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled)
|
||||
{
|
||||
this.renderTransparentBuffers(profiler, renderEventParam, renderEventParam.partialTicks);
|
||||
|
||||
|
||||
if (Config.Client.Advanced.Graphics.Fog.drawMode.get() != EDhApiFogDrawMode.FOG_DISABLED)
|
||||
{
|
||||
profiler.popPush("LOD Fog");
|
||||
|
||||
Mat4f combinedMatrix = new Mat4f(renderEventParam.dhProjectionMatrix);
|
||||
combinedMatrix.multiply(renderEventParam.dhModelViewMatrix);
|
||||
|
||||
FogRenderer.INSTANCE.render(minecraftGlState, combinedMatrix, renderEventParam.partialTicks);
|
||||
}
|
||||
}
|
||||
|
||||
drawLagSpikeCatcher.end("LodTranslucentDraw");
|
||||
@@ -469,56 +516,14 @@ public class LodRenderer
|
||||
this.bufferHandler.renderTransparent(this, renderEventParam);
|
||||
GL32.glDepthMask(true); // Apparently the depth mask state is stored in the FBO, so glState fails to restore it...
|
||||
|
||||
}
|
||||
|
||||
/** called by each {@link ColumnRenderBuffer} before rendering */
|
||||
public void setModelViewMatrixOffset(DhBlockPos pos, DhApiRenderParam renderEventParam) throws IllegalStateException
|
||||
{
|
||||
Vec3d cam = MC_RENDER.getCameraExactPosition();
|
||||
Vec3f modelPos = new Vec3f((float) (pos.x - cam.x), (float) (pos.y - cam.y), (float) (pos.z - cam.z));
|
||||
|
||||
|
||||
IDhApiShaderProgram shaderProgram = this.lodRenderProgram;
|
||||
IDhApiShaderProgram shaderProgramOverride = OverrideInjector.INSTANCE.get(IDhApiShaderProgram.class);
|
||||
if (shaderProgramOverride != null && shaderProgram.overrideThisFrame())
|
||||
if (Config.Client.Advanced.Graphics.Fog.drawMode.get() != EDhApiFogDrawMode.FOG_DISABLED)
|
||||
{
|
||||
shaderProgram = shaderProgramOverride;
|
||||
profiler.popPush("LOD Fog");
|
||||
FogShader.INSTANCE.render(partialTicks);
|
||||
}
|
||||
|
||||
shaderProgram.bind();
|
||||
shaderProgram.setModelOffsetPos(modelPos);
|
||||
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeBufferRenderEvent.class, new DhApiBeforeBufferRenderEvent.EventParam(renderEventParam, modelPos));
|
||||
}
|
||||
|
||||
public void drawVbo(GLVertexBuffer vbo)
|
||||
{
|
||||
//// can be uncommented to add additional debug validation to prevent crashes if invalid buffers are being created
|
||||
//// shouldn't be used in production due to the performance hit
|
||||
//if (GL32.glIsBuffer(vbo.getId()))
|
||||
{
|
||||
IDhApiShaderProgram shaderProgram = this.lodRenderProgram;
|
||||
IDhApiShaderProgram shaderProgramOverride = OverrideInjector.INSTANCE.get(IDhApiShaderProgram.class);
|
||||
if (shaderProgramOverride != null && shaderProgram.overrideThisFrame())
|
||||
{
|
||||
shaderProgram = shaderProgramOverride;
|
||||
}
|
||||
|
||||
|
||||
vbo.bind();
|
||||
shaderProgram.bindVertexBuffer(vbo.getId());
|
||||
GL32.glDrawElements(GL32.GL_TRIANGLES, (vbo.getVertexCount() / 4) * 6, // TODO what does the 4 and 6 here represent?
|
||||
this.quadIBO.getType(), 0);
|
||||
vbo.unbind();
|
||||
}
|
||||
//else
|
||||
//{
|
||||
// // will spam the log if uncommented, but helpful for validation
|
||||
// //LOGGER.warn("Unable to draw VBO: "+vbo.getId());
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//=================//
|
||||
@@ -611,7 +616,6 @@ public class LodRenderer
|
||||
boolean renderWireframe = Config.Client.Advanced.Debugging.renderWireframe.get();
|
||||
if (renderWireframe)
|
||||
{
|
||||
// TODO fix
|
||||
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_LINE);
|
||||
//GL32.glDisable(GL32.GL_CULL_FACE);
|
||||
}
|
||||
@@ -646,7 +650,7 @@ public class LodRenderer
|
||||
this.fogConfig = newFogConfig;
|
||||
|
||||
this.lodRenderProgram.free();
|
||||
this.lodRenderProgram = new DhTerrainShaderProgram();
|
||||
this.lodRenderProgram = new LodRenderProgram();
|
||||
|
||||
FogShader.INSTANCE.free();
|
||||
FogShader.INSTANCE = new FogShader(newFogConfig);
|
||||
@@ -686,7 +690,7 @@ public class LodRenderer
|
||||
|
||||
EVENT_LOGGER.info("Setting up renderer");
|
||||
this.isSetupComplete = true;
|
||||
this.lodRenderProgram = new DhTerrainShaderProgram();
|
||||
this.lodRenderProgram = new LodRenderProgram();
|
||||
if (ENABLE_IBO)
|
||||
{
|
||||
this.quadIBO = new QuadElementBuffer();
|
||||
@@ -864,35 +868,4 @@ public class LodRenderer
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper classes //
|
||||
//================//
|
||||
|
||||
public static class LagSpikeCatcher
|
||||
{
|
||||
long timer = System.nanoTime();
|
||||
|
||||
public LagSpikeCatcher() { }
|
||||
|
||||
public void end(String source)
|
||||
{
|
||||
if (!ENABLE_DRAW_LAG_SPIKE_LOGGING)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.timer = System.nanoTime() - this.timer;
|
||||
if (this.timer > DRAW_LAG_SPIKE_THRESHOLD_NS)
|
||||
{
|
||||
//4 ms
|
||||
EVENT_LOGGER.debug("NOTE: " + source + " took " + Duration.ofNanos(this.timer) + "!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+4
-7
@@ -24,7 +24,7 @@ import com.seibel.distanthorizons.core.render.glObject.GLState;
|
||||
import com.seibel.distanthorizons.core.render.renderer.shaders.SSAOApplyShader;
|
||||
import com.seibel.distanthorizons.core.render.renderer.shaders.SSAOShader;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.coreapi.util.math.Mat4f;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
@@ -51,7 +51,6 @@ public class SSAORenderer
|
||||
private int ssaoTexture = -1;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
@@ -93,7 +92,6 @@ public class SSAORenderer
|
||||
}
|
||||
|
||||
|
||||
|
||||
//========//
|
||||
// render //
|
||||
//========//
|
||||
@@ -101,11 +99,12 @@ public class SSAORenderer
|
||||
public void render(GLState primaryState, Mat4f projectionMatrix, float partialTicks)
|
||||
{
|
||||
GLState state = new GLState();
|
||||
this.init();
|
||||
|
||||
// resize the framebuffer if necessary
|
||||
this.init();
|
||||
|
||||
int width = MC_RENDER.getTargetFrameBufferViewportWidth();
|
||||
int height = MC_RENDER.getTargetFrameBufferViewportHeight();
|
||||
|
||||
if (this.width != width || this.height != height)
|
||||
{
|
||||
this.width = width;
|
||||
@@ -117,7 +116,6 @@ public class SSAORenderer
|
||||
SSAOShader.INSTANCE.setProjectionMatrix(projectionMatrix);
|
||||
SSAOShader.INSTANCE.render(partialTicks);
|
||||
|
||||
// restored so we can write the SSAO texture to the main frame buffer
|
||||
primaryState.restore();
|
||||
|
||||
SSAOApplyShader.INSTANCE.ssaoTexture = this.ssaoTexture;
|
||||
@@ -131,5 +129,4 @@ public class SSAORenderer
|
||||
SSAOShader.INSTANCE.free();
|
||||
SSAOApplyShader.INSTANCE.free();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-241
@@ -1,241 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2023 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.core.render.renderer.generic;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial;
|
||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
|
||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
|
||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.pos.DhBlockPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO;
|
||||
import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
public class BeaconRenderHandler
|
||||
{
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
|
||||
private static final int BEAM_TOP_Y = 6_000;
|
||||
|
||||
|
||||
/** if this is null then the other handler is probably null too, but just in case */
|
||||
private final BeaconBeamRepo beaconBeamRepo;
|
||||
|
||||
private final IDhApiRenderableBoxGroup beaconBoxGroup;
|
||||
private final HashMap<DhBlockPos, AtomicInteger> beaconRefCountByBlockPos = new HashMap<>();
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public BeaconRenderHandler(@NotNull BeaconBeamRepo beaconBeamRepo, @NotNull GenericObjectRenderer renderer)
|
||||
{
|
||||
this.beaconBeamRepo = beaconBeamRepo;
|
||||
|
||||
this.beaconBoxGroup = GenericRenderObjectFactory.INSTANCE.createAbsolutePositionedGroup(ModInfo.NAME+":Beacons", new ArrayList<>(0));
|
||||
this.beaconBoxGroup.setBlockLight(LodUtil.MAX_MC_LIGHT);
|
||||
this.beaconBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT);
|
||||
this.beaconBoxGroup.setSsaoEnabled(false);
|
||||
this.beaconBoxGroup.setShading(DhApiRenderableBoxGroupShading.getUnshaded());
|
||||
this.beaconBoxGroup.setPreRenderFunc((renderEventParam) -> this.beaconBoxGroup.setActive(Config.Client.Advanced.Graphics.GenericRendering.enableBeaconRendering.get()));
|
||||
|
||||
renderer.add(this.beaconBoxGroup);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=========================//
|
||||
// level loading/unloading //
|
||||
//=========================//
|
||||
|
||||
public void setBeaconBeamsForChunk(DhChunkPos chunkPos, List<BeaconBeamDTO> newBeamList)
|
||||
{
|
||||
// synchronized to prevent two threads from updating the same chunk at the same time
|
||||
synchronized (this)
|
||||
{
|
||||
HashSet<DhBlockPos> allPosSet = new HashSet<>();
|
||||
|
||||
// sort new beams
|
||||
HashMap<DhBlockPos, BeaconBeamDTO> newBeamByPos = new HashMap<>(newBeamList.size());
|
||||
for (int i = 0; i < newBeamList.size(); i++)
|
||||
{
|
||||
BeaconBeamDTO beam = newBeamList.get(i);
|
||||
newBeamByPos.put(beam.pos, beam);
|
||||
allPosSet.add(beam.pos);
|
||||
}
|
||||
|
||||
// get existing beams
|
||||
List<BeaconBeamDTO> existingBeamList = this.beaconBeamRepo.getAllBeamsForPos(chunkPos);
|
||||
HashMap<DhBlockPos, BeaconBeamDTO> existingBeamByPos = new HashMap<>(existingBeamList.size());
|
||||
for (int i = 0; i < existingBeamList.size(); i++)
|
||||
{
|
||||
BeaconBeamDTO beam = existingBeamList.get(i);
|
||||
existingBeamByPos.put(beam.pos, beam);
|
||||
allPosSet.add(beam.pos);
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (DhBlockPos beaconPos : allPosSet)
|
||||
{
|
||||
if (!chunkPos.contains(beaconPos))
|
||||
{
|
||||
// don't update beacons outside the updated chunk
|
||||
continue;
|
||||
}
|
||||
|
||||
BeaconBeamDTO existingBeam = existingBeamByPos.get(beaconPos);
|
||||
BeaconBeamDTO newBeam = newBeamByPos.get(beaconPos);
|
||||
|
||||
if (existingBeam != null && newBeam != null)
|
||||
{
|
||||
// beam still exists in chunk
|
||||
if (!existingBeam.color.equals(newBeam.color))
|
||||
{
|
||||
// beam colors were changed
|
||||
this.beaconBeamRepo.save(newBeam);
|
||||
this.updateBeaconColor(newBeam);
|
||||
}
|
||||
}
|
||||
else if (existingBeam == null && newBeam != null)
|
||||
{
|
||||
// new beam found, add to DB
|
||||
this.beaconBeamRepo.save(newBeam);
|
||||
this.startRenderingBeacon(newBeam);
|
||||
}
|
||||
else if (existingBeam != null && newBeam == null)
|
||||
{
|
||||
// beam no longer exists at position, remove from DB
|
||||
this.beaconBeamRepo.deleteWithKey(beaconPos); // TODO broken when updating adjacent chunks
|
||||
this.stopRenderingBeaconAtPos(beaconPos);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void loadBeaconBeamsInPos(long pos)
|
||||
{
|
||||
// get all beams in pos
|
||||
List<BeaconBeamDTO> existingBeamList = this.beaconBeamRepo.getAllBeamsForPos(pos);
|
||||
for (int i = 0; i < existingBeamList.size(); i++)
|
||||
{
|
||||
BeaconBeamDTO newBeam = existingBeamList.get(i);
|
||||
this.startRenderingBeacon(newBeam);
|
||||
}
|
||||
}
|
||||
|
||||
public void unloadBeaconBeamsInPos(long pos)
|
||||
{
|
||||
// get all beams in pos
|
||||
List<BeaconBeamDTO> existingBeamList = this.beaconBeamRepo.getAllBeamsForPos(pos);
|
||||
for (int i = 0; i < existingBeamList.size(); i++)
|
||||
{
|
||||
BeaconBeamDTO beam = existingBeamList.get(i);
|
||||
this.stopRenderingBeaconAtPos(beam.pos);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=================//
|
||||
// render handling //
|
||||
//=================//
|
||||
|
||||
private void startRenderingBeacon(BeaconBeamDTO beacon)
|
||||
{
|
||||
this.beaconRefCountByBlockPos.compute(beacon.pos, (beamPos, beaconRefCount) ->
|
||||
{
|
||||
if (beaconRefCount == null) { beaconRefCount = new AtomicInteger(); }
|
||||
if (beaconRefCount.getAndIncrement() == 0)
|
||||
{
|
||||
DhApiRenderableBox beaconBox = new DhApiRenderableBox(
|
||||
new DhApiVec3d(beacon.pos.x, beacon.pos.y+1, beacon.pos.z),
|
||||
new DhApiVec3d(beacon.pos.x+1, BEAM_TOP_Y, beacon.pos.z+1),
|
||||
beacon.color,
|
||||
EDhApiBlockMaterial.ILLUMINATED
|
||||
);
|
||||
|
||||
this.beaconBoxGroup.add(beaconBox);
|
||||
this.beaconBoxGroup.triggerBoxChange();
|
||||
}
|
||||
return beaconRefCount;
|
||||
});
|
||||
}
|
||||
|
||||
private void stopRenderingBeaconAtPos(DhBlockPos beaconPos)
|
||||
{
|
||||
this.beaconRefCountByBlockPos.compute(beaconPos, (pos, beaconRefCount) ->
|
||||
{
|
||||
if (beaconRefCount != null
|
||||
&& beaconRefCount.decrementAndGet() <= 0)
|
||||
{
|
||||
this.beaconBoxGroup.removeIf((box) ->
|
||||
box.minPos.x == beaconPos.x
|
||||
&& box.minPos.y == beaconPos.y+1 // plus 1 because the beam starts above the beacon
|
||||
&& box.minPos.z == beaconPos.z
|
||||
);
|
||||
this.beaconBoxGroup.triggerBoxChange();
|
||||
return null;
|
||||
}
|
||||
else
|
||||
{
|
||||
return beaconRefCount;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateBeaconColor(BeaconBeamDTO newBeam)
|
||||
{
|
||||
DhBlockPos pos = newBeam.pos;
|
||||
for (int i = 0; i < this.beaconBoxGroup.size(); i++)
|
||||
{
|
||||
DhApiRenderableBox box = this.beaconBoxGroup.get(i);
|
||||
if (box.minPos.x == pos.x
|
||||
&& box.minPos.y == pos.y+1 // plus 1 because the beam starts above the beacon
|
||||
&& box.minPos.z == pos.z)
|
||||
{
|
||||
box.color = newBeam.color;
|
||||
this.beaconBoxGroup.triggerBoxChange();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
-403
@@ -1,403 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2023 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.core.render.renderer.generic;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial;
|
||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
|
||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
|
||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.level.IDhLevel;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.*;
|
||||
|
||||
public class CloudRenderHandler
|
||||
{
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
|
||||
private static final String CLOUD_RESOURCE_TEXTURE_PATH = "assets/distanthorizons/textures/clouds.png";
|
||||
// FIXME transparency sorting makes having transparent clouds impossible
|
||||
private static final Color CLOUD_COLOR = new Color(255,255,255,255);
|
||||
|
||||
private static final boolean DEBUG_BORDER_COLORS = false;
|
||||
|
||||
/**
|
||||
* How wide an individual box is. <br>
|
||||
* Measured in blocks.
|
||||
*/
|
||||
private static final int CLOUD_BOX_WIDTH = 64;
|
||||
/** measured in blocks */
|
||||
private static final int CLOUD_BOX_THICKNESS = 16;
|
||||
|
||||
private final IDhApiRenderableBoxGroup[][] boxGroupByOffset = new IDhApiRenderableBoxGroup[3][3];
|
||||
private final IDhLevel level;
|
||||
private final GenericObjectRenderer renderer;
|
||||
|
||||
private float moveSpeedInBlocksPerSecond = 3.0f;
|
||||
private boolean disabledWarningLogged = false;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public CloudRenderHandler(IDhLevel level, GenericObjectRenderer renderer)
|
||||
{
|
||||
this.level = level;
|
||||
this.renderer = renderer;
|
||||
|
||||
|
||||
|
||||
//=======================//
|
||||
// get the cloud texture //
|
||||
//=======================//
|
||||
|
||||
// default to a single empty slot in case the texture is broken
|
||||
boolean[][] cloudLocations = new boolean[1][1];
|
||||
try
|
||||
{
|
||||
cloudLocations = getCloudsFromTexture();
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
LOGGER.error(e.getMessage(), e);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOGGER.error("Unexpected issue getting cloud texture, error: ["+e.getMessage()+"].", e);
|
||||
}
|
||||
|
||||
if (cloudLocations.length != 0 &&
|
||||
cloudLocations.length != cloudLocations[0].length)
|
||||
{
|
||||
LOGGER.warn("Non-square cloud texture found, some parts of the texture will be clipped off.");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//===================//
|
||||
// parse the texture //
|
||||
//===================//
|
||||
|
||||
int textureWidth = cloudLocations.length;
|
||||
ArrayList<DhApiRenderableBox> boxList = new ArrayList<>(512);
|
||||
for (int x = 0; x < textureWidth; x ++)
|
||||
{
|
||||
for (int z = 0; z < textureWidth; z ++)
|
||||
{
|
||||
if (cloudLocations[x][z])
|
||||
{
|
||||
// start a new box in Z direction
|
||||
int startZ = z;
|
||||
int startX = x;
|
||||
int endZ = startZ;
|
||||
int endX = x+1;
|
||||
|
||||
|
||||
|
||||
//==========================//
|
||||
// merge in the Z direction //
|
||||
//==========================//
|
||||
|
||||
// Find the cloud's length in the Z direction
|
||||
while (endZ < textureWidth
|
||||
&& cloudLocations[x][endZ])
|
||||
{
|
||||
endZ++;
|
||||
}
|
||||
// update the z iterator so we can skip over everything included in this cloud
|
||||
z = endZ - 1;
|
||||
|
||||
|
||||
|
||||
//==========================//
|
||||
// merge in the X direction //
|
||||
//==========================//
|
||||
|
||||
for (int currentX = startX + 1; currentX < textureWidth; currentX++)
|
||||
{
|
||||
boolean canMergeInXDir = true;
|
||||
|
||||
// check if all locations in this column are true
|
||||
for (int adjacentZ = startZ; adjacentZ < endZ; adjacentZ++)
|
||||
{
|
||||
if (!cloudLocations[currentX][adjacentZ])
|
||||
{
|
||||
// at least one pixel in the texture is false,
|
||||
// so we can't merge in this direction
|
||||
canMergeInXDir = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (canMergeInXDir)
|
||||
{
|
||||
// mark the adjacent column as processed
|
||||
for (int currentZ = startZ; currentZ < endZ; currentZ++)
|
||||
{
|
||||
// by flipping all the pixels in the adjacent column to false,
|
||||
// we don't have to worry about adding another cloud
|
||||
cloudLocations[currentX][currentZ] = false;
|
||||
}
|
||||
|
||||
endX = (currentX + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//============================//
|
||||
// Create the renderable box //
|
||||
//============================//
|
||||
|
||||
// endZ contains the last cloud index
|
||||
// so the cloud now goes from startZ to endZ (inclusive)
|
||||
int minXBlockPos = startX * CLOUD_BOX_WIDTH;
|
||||
int minZBlockPos = startZ * CLOUD_BOX_WIDTH;
|
||||
int maxXBlockPos = endX * CLOUD_BOX_WIDTH;
|
||||
int maxZBlockPos = endZ * CLOUD_BOX_WIDTH;
|
||||
|
||||
Color color = CLOUD_COLOR;
|
||||
if (DEBUG_BORDER_COLORS)
|
||||
{
|
||||
// equals is included so the board is 2 blocks wide, it makes it easier to see
|
||||
if (startX <= 1) { color = Color.RED; }
|
||||
else if (startX >= textureWidth - 2) { color = Color.GREEN; }
|
||||
if (startZ <= 1) { color = Color.BLUE; }
|
||||
else if (endZ >= textureWidth - 2) { color = Color.BLACK; }
|
||||
}
|
||||
|
||||
DhApiRenderableBox box = new DhApiRenderableBox(
|
||||
new DhApiVec3d(minXBlockPos, 0, minZBlockPos),
|
||||
new DhApiVec3d(maxXBlockPos, CLOUD_BOX_THICKNESS, maxZBlockPos),
|
||||
color,
|
||||
EDhApiBlockMaterial.UNKNOWN
|
||||
);
|
||||
boxList.add(box);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//========================//
|
||||
// create the renderables //
|
||||
//========================//
|
||||
|
||||
// slightly lighter shading than the default
|
||||
DhApiRenderableBoxGroupShading cloudShading = DhApiRenderableBoxGroupShading.getUnshaded();
|
||||
cloudShading.north = cloudShading.south = 0.9f;
|
||||
cloudShading.east = cloudShading.west = 0.8f;
|
||||
cloudShading.top = 1.0f;
|
||||
cloudShading.bottom = 0.7f;
|
||||
|
||||
// 3x3 area so we clouds should always be overhead
|
||||
for (int x = -1; x <= 1; x++)
|
||||
{
|
||||
for (int z = -1; z <= 1; z++)
|
||||
{
|
||||
IDhApiRenderableBoxGroup boxGroup = GenericRenderObjectFactory.INSTANCE.createRelativePositionedGroup(
|
||||
ModInfo.NAME + ":Clouds",
|
||||
new DhApiVec3d(0, 0, 0), // the offset will be set during rendering
|
||||
boxList);
|
||||
boxGroup.setBlockLight(LodUtil.MIN_MC_LIGHT);
|
||||
boxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT);
|
||||
boxGroup.setSsaoEnabled(false);
|
||||
boxGroup.setShading(cloudShading);
|
||||
|
||||
CloudParams params = new CloudParams(textureWidth, x, z);
|
||||
boxGroup.setPreRenderFunc((renderParam) -> this.preRender(params));
|
||||
|
||||
renderer.add(boxGroup);
|
||||
this.boxGroupByOffset[x+1][z+1] = boxGroup;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void preRender(CloudParams clouds)
|
||||
{
|
||||
IDhApiRenderableBoxGroup boxGroup = this.boxGroupByOffset[clouds.instanceOffsetX+1][clouds.instanceOffsetZ+1];
|
||||
|
||||
boolean renderClouds = Config.Client.Advanced.Graphics.GenericRendering.enableCloudRendering.get();
|
||||
boxGroup.setActive(renderClouds);
|
||||
if(!renderClouds)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.renderer.getUseInstancedRendering())
|
||||
{
|
||||
if (!this.disabledWarningLogged)
|
||||
{
|
||||
this.disabledWarningLogged = true;
|
||||
LOGGER.warn("Instanced rendering unavailable, cloud rendering disabled.");
|
||||
}
|
||||
boxGroup.setActive(false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//================//
|
||||
// cloud movement //
|
||||
//================//
|
||||
|
||||
long currentTime = System.currentTimeMillis();
|
||||
float deltaTime = (currentTime - clouds.lastFrameTime) / 1000.0f; // Delta time in seconds
|
||||
clouds.lastFrameTime = currentTime;
|
||||
|
||||
float deltaX = this.moveSpeedInBlocksPerSecond * deltaTime;
|
||||
// negative delta is to match vanilla's cloud movement
|
||||
clouds.xOffset -= deltaX;
|
||||
// wrap the cloud around after reaching the edge
|
||||
clouds.xOffset %= clouds.widthInBlocks;
|
||||
|
||||
|
||||
|
||||
//============================//
|
||||
// camera movement and offset //
|
||||
//============================//
|
||||
|
||||
// camera position
|
||||
int cameraPosX = (int)MC_RENDER.getCameraExactPosition().x;
|
||||
int cameraPosZ = (int)MC_RENDER.getCameraExactPosition().z;
|
||||
// offset the camera position by negative 1 width when below zero to fix off-by-one errors in the negative direction
|
||||
if (cameraPosX < 0) { cameraPosX -= clouds.widthInBlocks; }
|
||||
if (cameraPosZ < 0) { cameraPosZ -= clouds.widthInBlocks; }
|
||||
|
||||
// determine how many cloud instances away from the origin we are
|
||||
int cloudInstanceOffsetX = cameraPosX / (int)clouds.widthInBlocks;
|
||||
int cloudInstanceOffsetZ = cameraPosZ / (int)clouds.widthInBlocks;
|
||||
|
||||
// calculate the new offset
|
||||
float xOffset = (cloudInstanceOffsetX * clouds.widthInBlocks);
|
||||
float zOffset = (cloudInstanceOffsetZ * clouds.widthInBlocks);
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// update group //
|
||||
//==============//
|
||||
|
||||
boxGroup.setOriginBlockPos(
|
||||
new DhApiVec3d(
|
||||
clouds.xOffset + (clouds.instanceOffsetX * clouds.widthInBlocks) + xOffset + clouds.halfWidthInBlocks,
|
||||
this.level.getLevelWrapper().getMaxHeight() + 200,
|
||||
clouds.zOffset + (clouds.instanceOffsetZ * clouds.widthInBlocks) + zOffset + clouds.halfWidthInBlocks
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==================//
|
||||
// texture handling //
|
||||
//==================//
|
||||
|
||||
private static boolean[][] getCloudsFromTexture() throws FileNotFoundException, IOException
|
||||
{
|
||||
final ClassLoader loader = Thread.currentThread().getContextClassLoader();
|
||||
|
||||
boolean[][] whitePixels = null;
|
||||
try(InputStream imageInputStream = loader.getResourceAsStream(CLOUD_RESOURCE_TEXTURE_PATH))
|
||||
{
|
||||
if (imageInputStream == null)
|
||||
{
|
||||
throw new FileNotFoundException("Unable to find cloud texture at resource path: ["+CLOUD_RESOURCE_TEXTURE_PATH+"].");
|
||||
}
|
||||
|
||||
BufferedImage image = ImageIO.read(imageInputStream);
|
||||
|
||||
int width = image.getWidth();
|
||||
int height = image.getHeight();
|
||||
|
||||
whitePixels = new boolean[width][height];
|
||||
|
||||
for (int x = 0; x < width; x ++)
|
||||
{
|
||||
for (int z = 0; z < width; z ++)
|
||||
{
|
||||
Color color = new Color(image.getRGB(x,z));
|
||||
whitePixels[x][z] = color.equals(Color.WHITE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return whitePixels;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// helper classes //
|
||||
//================//
|
||||
|
||||
private static class CloudParams
|
||||
{
|
||||
public final float textureWidth;
|
||||
public final float widthInBlocks;
|
||||
public final float halfWidthInBlocks;
|
||||
|
||||
public final int instanceOffsetX;
|
||||
public final int instanceOffsetZ;
|
||||
|
||||
|
||||
public float xOffset = 0;
|
||||
public float zOffset = 0;
|
||||
|
||||
public long lastFrameTime = System.currentTimeMillis();
|
||||
|
||||
|
||||
|
||||
// constructor //
|
||||
|
||||
public CloudParams(float textureWidth, int instanceOffsetX, int instanceOffsetZ)
|
||||
{
|
||||
this.textureWidth = textureWidth;
|
||||
this.widthInBlocks = (this.textureWidth * CLOUD_BOX_WIDTH);
|
||||
this.halfWidthInBlocks = this.widthInBlocks / 2;
|
||||
|
||||
this.instanceOffsetX = instanceOffsetX;
|
||||
this.instanceOffsetZ = instanceOffsetZ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
-607
@@ -1,607 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2023 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.core.render.renderer.generic;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiGpuUploadMethod;
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiLoggerMode;
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial;
|
||||
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiGenericObjectShaderProgram;
|
||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
|
||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.*;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
|
||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
|
||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.logging.ConfigBasedSpamLogger;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.logging.f3.F3Screen;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLState;
|
||||
import com.seibel.distanthorizons.core.render.glObject.buffer.GLElementBuffer;
|
||||
import com.seibel.distanthorizons.core.render.glObject.buffer.GLVertexBuffer;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
|
||||
import com.seibel.distanthorizons.coreapi.DependencyInjection.OverrideInjector;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.lwjgl.opengl.ARBInstancedArrays;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
import org.lwjgl.opengl.GL33;
|
||||
|
||||
import java.awt.*;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Handles rendering generic groups of {@link DhApiRenderableBox}.
|
||||
*
|
||||
* @see IDhApiCustomRenderRegister
|
||||
* @see DhApiRenderableBox
|
||||
*/
|
||||
public class GenericObjectRenderer implements IDhApiCustomRenderRegister
|
||||
{
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
public static final ConfigBasedSpamLogger SPAM_LOGGER = new ConfigBasedSpamLogger(LogManager.getLogger(GenericObjectRenderer.class), () -> EDhApiLoggerMode.LOG_ALL_TO_CHAT, 1);
|
||||
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
|
||||
/**
|
||||
* Can be used to troubleshoot the renderer.
|
||||
* If enabled several debug objects will render around (0,150,0).
|
||||
*/
|
||||
public static final boolean RENDER_DEBUG_OBJECTS = false;
|
||||
|
||||
|
||||
// rendering setup
|
||||
private boolean init = false;
|
||||
|
||||
private IDhApiGenericObjectShaderProgram shaderProgram;
|
||||
private GLVertexBuffer boxVertexBuffer;
|
||||
private GLElementBuffer boxIndexBuffer;
|
||||
|
||||
private boolean useInstancedRendering;
|
||||
private boolean vertexAttribDivisorSupported;
|
||||
private boolean instancedArraysSupported;
|
||||
|
||||
|
||||
|
||||
private final ConcurrentHashMap<Long, RenderableBoxGroup> boxGroupById = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
|
||||
/** A box from 0,0,0 to 1,1,1 */
|
||||
private static final float[] BOX_VERTICES = {
|
||||
// Pos x y z
|
||||
|
||||
// min X, vertical face
|
||||
0, 0, 0,
|
||||
1, 0, 0,
|
||||
1, 1, 0,
|
||||
0, 1, 0,
|
||||
// max X, vertical face
|
||||
0, 1, 1,
|
||||
1, 1, 1,
|
||||
1, 0, 1,
|
||||
0, 0, 1,
|
||||
|
||||
// min Z, vertical face
|
||||
0, 0, 1,
|
||||
0, 0, 0,
|
||||
0, 1, 0,
|
||||
0, 1, 1,
|
||||
// max Z, vertical face
|
||||
1, 0, 1,
|
||||
1, 1, 1,
|
||||
1, 1, 0,
|
||||
1, 0, 0,
|
||||
|
||||
// min Y, horizontal face
|
||||
0, 0, 1,
|
||||
1, 0, 1,
|
||||
1, 0, 0,
|
||||
0, 0, 0,
|
||||
// max Y, horizontal face
|
||||
0, 1, 1,
|
||||
1, 1, 1,
|
||||
1, 1, 0,
|
||||
0, 1, 0,
|
||||
};
|
||||
|
||||
private static final int[] BOX_INDICES = {
|
||||
// min X, vertical face
|
||||
2, 1, 0,
|
||||
0, 3, 2,
|
||||
// max X, vertical face
|
||||
6, 5, 4,
|
||||
4, 7, 6,
|
||||
|
||||
// min Z, vertical face
|
||||
10, 9, 8,
|
||||
8, 11, 10,
|
||||
// max Z, vertical face
|
||||
14, 13, 12,
|
||||
12, 15, 14,
|
||||
|
||||
// min Y, horizontal face
|
||||
18, 17, 16,
|
||||
16, 19, 18,
|
||||
// max Y, horizontal face
|
||||
20, 21, 22,
|
||||
22, 23, 20,
|
||||
};
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public GenericObjectRenderer() { }
|
||||
|
||||
public void init()
|
||||
{
|
||||
if (this.init)
|
||||
{
|
||||
return;
|
||||
}
|
||||
this.init = true;
|
||||
|
||||
this.vertexAttribDivisorSupported = GLProxy.getInstance().vertexAttribDivisorSupported;
|
||||
this.instancedArraysSupported = GLProxy.getInstance().instancedArraysSupported;
|
||||
this.useInstancedRendering = this.vertexAttribDivisorSupported || this.instancedArraysSupported;
|
||||
if (!this.useInstancedRendering)
|
||||
{
|
||||
LOGGER.warn("Instanced rendering not supported by this GPU, falling back to direct rendering. Generic object rendering will be slow.");
|
||||
}
|
||||
|
||||
this.shaderProgram = new GenericObjectShaderProgram(this.useInstancedRendering);
|
||||
|
||||
|
||||
this.createBuffers();
|
||||
|
||||
if (RENDER_DEBUG_OBJECTS)
|
||||
{
|
||||
this.addGenericDebugObjects();
|
||||
}
|
||||
}
|
||||
private void createBuffers()
|
||||
{
|
||||
// box vertices
|
||||
ByteBuffer boxVerticesBuffer = ByteBuffer.allocateDirect(BOX_VERTICES.length * Float.BYTES);
|
||||
boxVerticesBuffer.order(ByteOrder.nativeOrder());
|
||||
boxVerticesBuffer.asFloatBuffer().put(BOX_VERTICES);
|
||||
boxVerticesBuffer.rewind();
|
||||
this.boxVertexBuffer = new GLVertexBuffer(false);
|
||||
this.boxVertexBuffer.bind();
|
||||
this.boxVertexBuffer.uploadBuffer(boxVerticesBuffer, 8, EDhApiGpuUploadMethod.DATA, BOX_VERTICES.length * Float.BYTES);
|
||||
|
||||
|
||||
// box vertex indexes
|
||||
ByteBuffer solidIndexBuffer = ByteBuffer.allocateDirect(BOX_INDICES.length * Integer.BYTES);
|
||||
solidIndexBuffer.order(ByteOrder.nativeOrder());
|
||||
solidIndexBuffer.asIntBuffer().put(BOX_INDICES);
|
||||
solidIndexBuffer.rewind();
|
||||
this.boxIndexBuffer = new GLElementBuffer(false);
|
||||
this.boxIndexBuffer.uploadBuffer(solidIndexBuffer, EDhApiGpuUploadMethod.DATA, BOX_INDICES.length * Integer.BYTES, GL32.GL_STATIC_DRAW);
|
||||
this.boxIndexBuffer.bind();
|
||||
|
||||
}
|
||||
private void addGenericDebugObjects()
|
||||
{
|
||||
GenericRenderObjectFactory factory = GenericRenderObjectFactory.INSTANCE;
|
||||
|
||||
|
||||
// single giant box
|
||||
IDhApiRenderableBoxGroup singleGiantBoxGroup = factory.createForSingleBox(
|
||||
ModInfo.NAME + ":CyanChunkBox",
|
||||
new DhApiRenderableBox(
|
||||
new DhApiVec3d(0,0,0), new DhApiVec3d(16,190,16),
|
||||
new Color(Color.CYAN.getRed(), Color.CYAN.getGreen(), Color.CYAN.getBlue(), 125),
|
||||
EDhApiBlockMaterial.WATER)
|
||||
);
|
||||
singleGiantBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT);
|
||||
singleGiantBoxGroup.setBlockLight(LodUtil.MAX_MC_LIGHT);
|
||||
this.add(singleGiantBoxGroup);
|
||||
|
||||
|
||||
// single slender box
|
||||
IDhApiRenderableBoxGroup singleTallBoxGroup = factory.createForSingleBox(
|
||||
ModInfo.NAME + ":GreenBeacon",
|
||||
new DhApiRenderableBox(
|
||||
new DhApiVec3d(16,0,31), new DhApiVec3d(17,2000,32),
|
||||
new Color(Color.GREEN.getRed(), Color.GREEN.getGreen(), Color.GREEN.getBlue(), 125),
|
||||
EDhApiBlockMaterial.ILLUMINATED)
|
||||
);
|
||||
singleTallBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT);
|
||||
singleTallBoxGroup.setBlockLight(LodUtil.MAX_MC_LIGHT);
|
||||
this.add(singleTallBoxGroup);
|
||||
|
||||
|
||||
// absolute box group
|
||||
ArrayList<DhApiRenderableBox> absBoxList = new ArrayList<>();
|
||||
for (int i = 0; i < 18; i++)
|
||||
{
|
||||
absBoxList.add(new DhApiRenderableBox(
|
||||
new DhApiVec3d(i,150+i,24), new DhApiVec3d(1+i,151+i,25),
|
||||
new Color(Color.ORANGE.getRed(), Color.ORANGE.getGreen(), Color.ORANGE.getBlue()),
|
||||
EDhApiBlockMaterial.LAVA
|
||||
)
|
||||
);
|
||||
}
|
||||
IDhApiRenderableBoxGroup absolutePosBoxGroup = factory.createAbsolutePositionedGroup(ModInfo.NAME + ":OrangeStairs", absBoxList);
|
||||
this.add(absolutePosBoxGroup);
|
||||
|
||||
|
||||
// relative box group
|
||||
ArrayList<DhApiRenderableBox> relBoxList = new ArrayList<>();
|
||||
for (int i = 0; i < 8; i+=2)
|
||||
{
|
||||
relBoxList.add(new DhApiRenderableBox(
|
||||
new DhApiVec3d(0,i,0), new DhApiVec3d(1,1+i,1),
|
||||
new Color(Color.MAGENTA.getRed(), Color.MAGENTA.getGreen(), Color.MAGENTA.getBlue()),
|
||||
EDhApiBlockMaterial.METAL
|
||||
)
|
||||
);
|
||||
}
|
||||
IDhApiRenderableBoxGroup relativePosBoxGroup = factory.createRelativePositionedGroup(
|
||||
ModInfo.NAME + ":MovingMagentaGroup",
|
||||
new DhApiVec3d(24, 140, 24),
|
||||
relBoxList);
|
||||
relativePosBoxGroup.setPreRenderFunc((event) ->
|
||||
{
|
||||
DhApiVec3d pos = relativePosBoxGroup.getOriginBlockPos();
|
||||
pos.x += event.partialTicks / 2;
|
||||
pos.x %= 32;
|
||||
relativePosBoxGroup.setOriginBlockPos(pos);
|
||||
});
|
||||
this.add(relativePosBoxGroup);
|
||||
|
||||
|
||||
// massive relative box group
|
||||
ArrayList<DhApiRenderableBox> massRelBoxList = new ArrayList<>();
|
||||
for (int x = 0; x < 50*2; x+=2)
|
||||
{
|
||||
for (int z = 0; z < 50*2; z+=2)
|
||||
{
|
||||
massRelBoxList.add(new DhApiRenderableBox(
|
||||
new DhApiVec3d(-x, 0, -z), new DhApiVec3d(1-x, 1, 1-z),
|
||||
new Color(Color.RED.getRed(), Color.RED.getGreen(), Color.RED.getBlue()),
|
||||
EDhApiBlockMaterial.TERRACOTTA
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
IDhApiRenderableBoxGroup massRelativePosBoxGroup = factory.createRelativePositionedGroup(
|
||||
ModInfo.NAME + ":MassRedGroup",
|
||||
new DhApiVec3d(-25, 140, 0),
|
||||
massRelBoxList);
|
||||
massRelativePosBoxGroup.setPreRenderFunc((event) ->
|
||||
{
|
||||
DhApiVec3d blockPos = massRelativePosBoxGroup.getOriginBlockPos();
|
||||
blockPos.y += event.partialTicks / 4;
|
||||
if (blockPos.y > 150f)
|
||||
{
|
||||
blockPos.y = 140f;
|
||||
|
||||
Color newColor = (massRelativePosBoxGroup.get(0).color == Color.RED) ? Color.RED.darker() : Color.RED;
|
||||
massRelativePosBoxGroup.forEach((box) -> { box.color = newColor; });
|
||||
massRelativePosBoxGroup.triggerBoxChange();
|
||||
}
|
||||
|
||||
massRelativePosBoxGroup.setOriginBlockPos(blockPos);
|
||||
});
|
||||
this.add(massRelativePosBoxGroup);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
// registration //
|
||||
//==============//
|
||||
|
||||
@Override
|
||||
public void add(IDhApiRenderableBoxGroup iBoxGroup) throws IllegalArgumentException
|
||||
{
|
||||
if (!(iBoxGroup instanceof RenderableBoxGroup))
|
||||
{
|
||||
throw new IllegalArgumentException("Box group must be of type ["+ RenderableBoxGroup.class.getSimpleName()+"], type received: ["+(iBoxGroup != null ? iBoxGroup.getClass() : "NULL")+"].");
|
||||
}
|
||||
RenderableBoxGroup boxGroup = (RenderableBoxGroup) iBoxGroup;
|
||||
|
||||
|
||||
long id = boxGroup.getId();
|
||||
if (this.boxGroupById.containsKey(id))
|
||||
{
|
||||
throw new IllegalArgumentException("A box group with the ID [" + id + "] is already present.");
|
||||
}
|
||||
|
||||
this.boxGroupById.put(id, boxGroup);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDhApiRenderableBoxGroup remove(long id) { return this.boxGroupById.remove(id); }
|
||||
|
||||
public void clear() { this.boxGroupById.clear(); }
|
||||
|
||||
|
||||
|
||||
//===========//
|
||||
// rendering //
|
||||
//===========//
|
||||
|
||||
/**
|
||||
* @param renderingWithSsao
|
||||
* if true that means this render call is happening before the SSAO pass
|
||||
* and any objects rendered in this pass will have SSAO applied to them.
|
||||
*/
|
||||
public void render(DhApiRenderParam renderEventParam, IProfilerWrapper profiler, boolean renderingWithSsao)
|
||||
{
|
||||
// render setup //
|
||||
profiler.push("setup");
|
||||
|
||||
GLState glState = new GLState();
|
||||
this.init();
|
||||
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericRenderSetupEvent.class, renderEventParam);
|
||||
|
||||
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL);
|
||||
GL32.glEnable(GL32.GL_DEPTH_TEST);
|
||||
|
||||
GL32.glEnable(GL32.GL_BLEND);
|
||||
GL32.glBlendEquation(GL32.GL_FUNC_ADD);
|
||||
GL32.glBlendFuncSeparate(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA, GL32.GL_ONE, GL32.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
IDhApiGenericObjectShaderProgram shaderProgram = this.shaderProgram;
|
||||
IDhApiGenericObjectShaderProgram shaderProgramOverride = OverrideInjector.INSTANCE.get(IDhApiGenericObjectShaderProgram.class);
|
||||
if (shaderProgramOverride != null && shaderProgram.overrideThisFrame())
|
||||
{
|
||||
shaderProgram = shaderProgramOverride;
|
||||
}
|
||||
|
||||
shaderProgram.bind(renderEventParam);
|
||||
shaderProgram.bindVertexBuffer(this.boxVertexBuffer.getId());
|
||||
|
||||
this.boxIndexBuffer.bind();
|
||||
|
||||
Vec3d camPos = MC_RENDER.getCameraExactPosition();
|
||||
|
||||
|
||||
|
||||
// rendering //
|
||||
|
||||
Collection<RenderableBoxGroup> boxList = this.boxGroupById.values();
|
||||
for (RenderableBoxGroup boxGroup : boxList)
|
||||
{
|
||||
// skip boxes that shouldn't render this pass
|
||||
if (boxGroup.ssaoEnabled == renderingWithSsao)
|
||||
{
|
||||
profiler.popPush("render prep");
|
||||
boxGroup.preRender(renderEventParam);
|
||||
|
||||
// ignore inactive groups
|
||||
if (boxGroup.active)
|
||||
{
|
||||
boolean cancelRendering = ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericObjectRenderEvent.class, new DhApiBeforeGenericObjectRenderEvent.EventParam(renderEventParam, boxGroup));
|
||||
if (!cancelRendering)
|
||||
{
|
||||
profiler.popPush("rendering");
|
||||
profiler.push(boxGroup.getResourceLocationNamespace());
|
||||
profiler.push(boxGroup.getResourceLocationPath());
|
||||
if (this.useInstancedRendering)
|
||||
{
|
||||
this.renderBoxGroupInstanced(shaderProgram, renderEventParam, boxGroup, camPos);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.renderBoxGroupDirect(shaderProgram, renderEventParam, boxGroup, camPos);
|
||||
}
|
||||
profiler.pop(); // resource path
|
||||
profiler.pop(); // resource namespace
|
||||
|
||||
boxGroup.postRender(renderEventParam);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// clean up //
|
||||
profiler.popPush("cleanup");
|
||||
|
||||
ApiEventInjector.INSTANCE.fireAllEvents(DhApiBeforeGenericRenderCleanupEvent.class, renderEventParam);
|
||||
|
||||
shaderProgram.unbind();
|
||||
glState.restore();
|
||||
|
||||
profiler.pop();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=====================//
|
||||
// instanced rendering //
|
||||
//=====================//
|
||||
|
||||
private void renderBoxGroupInstanced(IDhApiGenericObjectShaderProgram shaderProgram, DhApiRenderParam renderEventParam, RenderableBoxGroup boxGroup, Vec3d camPos)
|
||||
{
|
||||
// update instance data //
|
||||
|
||||
boxGroup.updateVertexAttributeData();
|
||||
|
||||
DhApiRenderableBoxGroupShading shading = boxGroup.shading;
|
||||
if (shading == null)
|
||||
{
|
||||
shading = DhApiRenderableBoxGroupShading.getUnshaded();
|
||||
}
|
||||
|
||||
shaderProgram.fillIndirectUniformData(
|
||||
renderEventParam,
|
||||
shading, boxGroup,
|
||||
camPos);
|
||||
|
||||
|
||||
|
||||
// Bind instance data //
|
||||
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instanceColorVbo);
|
||||
GL32.glEnableVertexAttribArray(1);
|
||||
GL32.glVertexAttribPointer(1, 4, GL32.GL_FLOAT, false, 4 * Float.BYTES, 0);
|
||||
this.vertexAttribDivisor(1, 1);
|
||||
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instanceScaleVbo);
|
||||
GL32.glEnableVertexAttribArray(2);
|
||||
this.vertexAttribDivisor(2, 1);
|
||||
GL32.glVertexAttribPointer(2, 3, GL32.GL_FLOAT, false, 3 * Float.BYTES, 0);
|
||||
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instanceChunkPosVbo);
|
||||
GL32.glEnableVertexAttribArray(3);
|
||||
this.vertexAttribDivisor(3, 1);
|
||||
GL32.glVertexAttribIPointer(3, 3, GL32.GL_INT, 3 * Integer.BYTES, 0);
|
||||
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instanceSubChunkPosVbo);
|
||||
GL32.glEnableVertexAttribArray(4);
|
||||
this.vertexAttribDivisor(4, 1);
|
||||
GL32.glVertexAttribPointer(4, 3, GL32.GL_FLOAT, false, 3 * Float.BYTES, 0);
|
||||
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instanceMaterialVbo);
|
||||
GL32.glEnableVertexAttribArray(5);
|
||||
this.vertexAttribDivisor(5, 1);
|
||||
GL32.glVertexAttribIPointer(5, 1, GL32.GL_BYTE, Byte.BYTES, 0);
|
||||
|
||||
|
||||
// Draw instanced
|
||||
if (boxGroup.uploadedBoxCount > 0)
|
||||
{
|
||||
GL32.glDrawElementsInstanced(GL32.GL_TRIANGLES, BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0, boxGroup.uploadedBoxCount);
|
||||
}
|
||||
|
||||
|
||||
// Clean up
|
||||
GL32.glDisableVertexAttribArray(1);
|
||||
GL32.glDisableVertexAttribArray(2);
|
||||
GL32.glDisableVertexAttribArray(3);
|
||||
GL32.glDisableVertexAttribArray(4);
|
||||
GL32.glDisableVertexAttribArray(5);
|
||||
}
|
||||
/**
|
||||
* Clean way to handle both {@link GL33#glVertexAttribDivisor} and {@link ARBInstancedArrays#glVertexAttribDivisorARB}
|
||||
* based on which one is supported.
|
||||
*/
|
||||
private void vertexAttribDivisor(int index, int divisor)
|
||||
{
|
||||
if (this.vertexAttribDivisorSupported)
|
||||
{
|
||||
GL33.glVertexAttribDivisor(index, divisor);
|
||||
}
|
||||
else if(this.instancedArraysSupported)
|
||||
{
|
||||
ARBInstancedArrays.glVertexAttribDivisorARB(index, divisor);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalStateException("Instanced rendering isn't supported by this machine. Direct rendering should have been used instead.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//==================//
|
||||
// direct rendering //
|
||||
//==================//
|
||||
|
||||
private void renderBoxGroupDirect(IDhApiGenericObjectShaderProgram shaderProgram, DhApiRenderParam renderEventParam, RenderableBoxGroup boxGroup, Vec3d camPos)
|
||||
{
|
||||
DhApiRenderableBoxGroupShading shading = boxGroup.shading;
|
||||
if (shading == null)
|
||||
{
|
||||
shading = DhApiRenderableBoxGroupShading.getUnshaded();
|
||||
}
|
||||
|
||||
shaderProgram.fillSharedDirectUniformData(renderEventParam, shading, boxGroup, camPos);
|
||||
|
||||
for (DhApiRenderableBox box : boxGroup)
|
||||
{
|
||||
this.renderBox(shaderProgram, renderEventParam, boxGroup, box, camPos);
|
||||
}
|
||||
}
|
||||
private void renderBox(
|
||||
IDhApiGenericObjectShaderProgram shaderProgram,
|
||||
DhApiRenderParam renderEventParam,
|
||||
RenderableBoxGroup boxGroup, DhApiRenderableBox box,
|
||||
Vec3d camPos)
|
||||
{
|
||||
shaderProgram.fillDirectUniformData(renderEventParam, boxGroup, box, camPos);
|
||||
GL32.glDrawElements(GL32.GL_TRIANGLES, BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// getters //
|
||||
//=========//
|
||||
|
||||
/** @throws IllegalStateException if {@link #init()} function hasn't been called yet */
|
||||
public boolean getUseInstancedRendering() throws IllegalStateException
|
||||
{
|
||||
if (!this.init)
|
||||
{
|
||||
throw new IllegalStateException("GL initialization hasn't been completed.");
|
||||
}
|
||||
|
||||
return this.useInstancedRendering;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// F3 menu //
|
||||
//=========//
|
||||
|
||||
public String getVboRenderDebugMenuString()
|
||||
{
|
||||
// get counts
|
||||
int totalCount = this.boxGroupById.size();
|
||||
int activeCount = 0;
|
||||
for (long key : this.boxGroupById.keySet())
|
||||
{
|
||||
RenderableBoxGroup renderGroup = this.boxGroupById.get(key);
|
||||
if (renderGroup.active)
|
||||
{
|
||||
activeCount++;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
String totalCountText = F3Screen.NUMBER_FORMAT.format(totalCount);
|
||||
String activeCountText = F3Screen.NUMBER_FORMAT.format(activeCount);
|
||||
return LodUtil.formatLog("Generic Obj Count: " + activeCountText + "/" + totalCountText);
|
||||
}
|
||||
|
||||
}
|
||||
-229
@@ -1,229 +0,0 @@
|
||||
package com.seibel.distanthorizons.core.render.renderer.generic;
|
||||
|
||||
import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiGenericObjectShaderProgram;
|
||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
|
||||
import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3i;
|
||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
|
||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading;
|
||||
import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
|
||||
import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.AbstractVertexAttribute;
|
||||
import com.seibel.distanthorizons.core.render.glObject.vertexAttribute.VertexPointer;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||
|
||||
public class GenericObjectShaderProgram extends ShaderProgram implements IDhApiGenericObjectShaderProgram
|
||||
{
|
||||
public static final String VERTEX_SHADER_INSTANCED_PATH = "shaders/genericObject/instanced/vert.vert";
|
||||
public static final String VERTEX_SHADER_DIRECT_PATH = "shaders/genericObject/direct/vert.vert";
|
||||
public static final String FRAGMENT_SHADER_INSTANCED_PATH = "shaders/genericObject/instanced/frag.frag";
|
||||
public static final String FRAGMENT_SHADER_DIRECT_PATH = "shaders/genericObject/direct/frag.frag";
|
||||
|
||||
public final AbstractVertexAttribute va;
|
||||
|
||||
|
||||
// shader uniforms
|
||||
private final int directShaderTransformUniform;
|
||||
private final int directShaderColorUniform;
|
||||
|
||||
private final int instancedShaderOffsetChunkUniform;
|
||||
private final int instancedShaderOffsetSubChunkUniform;
|
||||
private final int instancedShaderCameraChunkPosUniform;
|
||||
private final int instancedShaderCameraSubChunkPosUniform;
|
||||
private final int instancedShaderProjectionModelViewMatrixUniform;
|
||||
|
||||
private final int lightMapUniform;
|
||||
private final int skyLightUniform;
|
||||
private final int blockLightUniform;
|
||||
|
||||
private final int northShadingUniform;
|
||||
private final int southShadingUniform;
|
||||
private final int eastShadingUniform;
|
||||
private final int westShadingUniform;
|
||||
private final int topShadingUniform;
|
||||
private final int bottomShadingUniform;
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
public GenericObjectShaderProgram(boolean useInstancedRendering)
|
||||
{
|
||||
super(
|
||||
useInstancedRendering ? VERTEX_SHADER_INSTANCED_PATH : VERTEX_SHADER_DIRECT_PATH,
|
||||
useInstancedRendering ? FRAGMENT_SHADER_INSTANCED_PATH : FRAGMENT_SHADER_DIRECT_PATH,
|
||||
"fragColor", new String[]{"vPosition"});
|
||||
|
||||
this.va = AbstractVertexAttribute.create();
|
||||
this.va.bind();
|
||||
// Pos
|
||||
this.va.setVertexAttribute(0, 0, VertexPointer.addVec3Pointer(false));
|
||||
this.va.completeAndCheck(Float.BYTES * 3);
|
||||
|
||||
this.directShaderTransformUniform = this.tryGetUniformLocation("uTransform");
|
||||
this.directShaderColorUniform = this.tryGetUniformLocation("uColor");
|
||||
|
||||
this.instancedShaderOffsetChunkUniform = this.tryGetUniformLocation("uOffsetChunk");
|
||||
this.instancedShaderOffsetSubChunkUniform = this.tryGetUniformLocation("uOffsetSubChunk");
|
||||
this.instancedShaderCameraChunkPosUniform = this.tryGetUniformLocation("uCameraPosChunk");
|
||||
this.instancedShaderCameraSubChunkPosUniform = this.tryGetUniformLocation("uCameraPosSubChunk");
|
||||
this.instancedShaderProjectionModelViewMatrixUniform = this.tryGetUniformLocation("uProjectionMvm");
|
||||
|
||||
this.lightMapUniform = this.getUniformLocation("uLightMap");
|
||||
this.skyLightUniform = this.getUniformLocation("uSkyLight");
|
||||
this.blockLightUniform = this.getUniformLocation("uBlockLight");
|
||||
this.northShadingUniform = this.getUniformLocation("uNorthShading");
|
||||
this.southShadingUniform = this.getUniformLocation("uSouthShading");
|
||||
this.eastShadingUniform = this.getUniformLocation("uEastShading");
|
||||
this.westShadingUniform = this.getUniformLocation("uWestShading");
|
||||
this.topShadingUniform = this.getUniformLocation("uTopShading");
|
||||
this.bottomShadingUniform = this.getUniformLocation("uBottomShading");
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=========//
|
||||
// methods //
|
||||
//=========//
|
||||
|
||||
@Override
|
||||
public void bind(DhApiRenderParam renderEventParam)
|
||||
{
|
||||
super.bind();
|
||||
this.va.bind();
|
||||
}
|
||||
@Override
|
||||
public void unbind()
|
||||
{
|
||||
super.unbind();
|
||||
this.va.unbind();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void free()
|
||||
{
|
||||
this.va.free();
|
||||
super.free();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindVertexBuffer(int vbo) { this.va.bindBufferToAllBindingPoints(vbo); }
|
||||
|
||||
@Override
|
||||
public void fillIndirectUniformData(
|
||||
DhApiRenderParam renderParameters,
|
||||
DhApiRenderableBoxGroupShading shading, IDhApiRenderableBoxGroup boxGroup,
|
||||
DhApiVec3d camPos
|
||||
)
|
||||
{
|
||||
Mat4f projectionMvmMatrix = new Mat4f(renderParameters.dhProjectionMatrix);
|
||||
projectionMvmMatrix.multiply(renderParameters.dhModelViewMatrix);
|
||||
|
||||
super.bind();
|
||||
|
||||
|
||||
|
||||
|
||||
this.setUniform(this.instancedShaderOffsetChunkUniform,
|
||||
new DhApiVec3i(
|
||||
LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().x),
|
||||
LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().y),
|
||||
LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().z)
|
||||
));
|
||||
this.setUniform(this.instancedShaderOffsetSubChunkUniform,
|
||||
new Vec3f(
|
||||
LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().x),
|
||||
LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().y),
|
||||
LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().z)
|
||||
));
|
||||
|
||||
this.setUniform(this.instancedShaderCameraChunkPosUniform,
|
||||
new DhApiVec3i(
|
||||
LodUtil.getChunkPosFromDouble(camPos.x),
|
||||
LodUtil.getChunkPosFromDouble(camPos.y),
|
||||
LodUtil.getChunkPosFromDouble(camPos.z)
|
||||
));
|
||||
this.setUniform(this.instancedShaderCameraSubChunkPosUniform,
|
||||
new Vec3f(
|
||||
LodUtil.getSubChunkPosFromDouble(camPos.x),
|
||||
LodUtil.getSubChunkPosFromDouble(camPos.y),
|
||||
LodUtil.getSubChunkPosFromDouble(camPos.z)
|
||||
));
|
||||
|
||||
this.setUniform(this.instancedShaderProjectionModelViewMatrixUniform, projectionMvmMatrix);
|
||||
|
||||
this.setUniform(this.lightMapUniform, 0); // TODO this should probably be passed in
|
||||
this.setUniform(this.skyLightUniform, boxGroup.getSkyLight());
|
||||
this.setUniform(this.blockLightUniform, boxGroup.getBlockLight());
|
||||
|
||||
|
||||
this.setUniform(this.northShadingUniform, shading.north);
|
||||
this.setUniform(this.southShadingUniform, shading.south);
|
||||
this.setUniform(this.eastShadingUniform, shading.east);
|
||||
this.setUniform(this.westShadingUniform, shading.west);
|
||||
this.setUniform(this.topShadingUniform, shading.top);
|
||||
this.setUniform(this.bottomShadingUniform, shading.bottom);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void fillSharedDirectUniformData(
|
||||
DhApiRenderParam renderParameters,
|
||||
DhApiRenderableBoxGroupShading shading, IDhApiRenderableBoxGroup boxGroup,
|
||||
DhApiVec3d camPos)
|
||||
{
|
||||
|
||||
this.setUniform(this.lightMapUniform, 0); // TODO this should probably be passed in
|
||||
this.setUniform(this.skyLightUniform, boxGroup.getSkyLight());
|
||||
this.setUniform(this.blockLightUniform, boxGroup.getBlockLight());
|
||||
|
||||
|
||||
this.setUniform(this.northShadingUniform, shading.north);
|
||||
this.setUniform(this.southShadingUniform, shading.south);
|
||||
this.setUniform(this.eastShadingUniform, shading.east);
|
||||
this.setUniform(this.westShadingUniform, shading.west);
|
||||
this.setUniform(this.topShadingUniform, shading.top);
|
||||
this.setUniform(this.bottomShadingUniform, shading.bottom);
|
||||
|
||||
}
|
||||
|
||||
public void fillDirectUniformData(
|
||||
DhApiRenderParam renderParameters,
|
||||
IDhApiRenderableBoxGroup boxGroup, DhApiRenderableBox box,
|
||||
DhApiVec3d camPos)
|
||||
{
|
||||
Mat4f projectionMvmMatrix = new Mat4f(renderParameters.dhProjectionMatrix);
|
||||
projectionMvmMatrix.multiply(renderParameters.dhModelViewMatrix);
|
||||
|
||||
Mat4f boxTransform = Mat4f.createTranslateMatrix(
|
||||
(float) (box.minPos.x + boxGroup.getOriginBlockPos().x - camPos.x),
|
||||
(float) (box.minPos.y + boxGroup.getOriginBlockPos().y - camPos.y),
|
||||
(float) (box.minPos.z + boxGroup.getOriginBlockPos().z - camPos.z));
|
||||
boxTransform.multiply(Mat4f.createScaleMatrix(
|
||||
(float) (box.maxPos.x - box.minPos.x),
|
||||
(float) (box.maxPos.y - box.minPos.y),
|
||||
(float) (box.maxPos.z - box.minPos.z)));
|
||||
projectionMvmMatrix.multiply(boxTransform);
|
||||
this.setUniform(this.directShaderTransformUniform, projectionMvmMatrix);
|
||||
|
||||
this.setUniform(this.directShaderColorUniform, box.color);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public int getId() { return this.id; }
|
||||
|
||||
/** The base DH render program should always render */
|
||||
@Override
|
||||
public boolean overrideThisFrame() { return true; }
|
||||
|
||||
}
|
||||
-78
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizons mod
|
||||
* licensed under the GNU LGPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020-2023 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.distanthorizons.core.render.renderer.generic;
|
||||
|
||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderObjectFactory;
|
||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister;
|
||||
import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
|
||||
import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
|
||||
import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3d;
|
||||
import com.seibel.distanthorizons.core.util.math.Vec3f;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Handles creating {@link DhApiRenderableBox}.
|
||||
*
|
||||
* @see IDhApiCustomRenderRegister
|
||||
* @see DhApiRenderableBox
|
||||
*/
|
||||
public class GenericRenderObjectFactory implements IDhApiCustomRenderObjectFactory
|
||||
{
|
||||
private static final Logger LOGGER = DhLoggerBuilder.getLogger();
|
||||
|
||||
public static final GenericRenderObjectFactory INSTANCE = new GenericRenderObjectFactory();
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
private GenericRenderObjectFactory() { }
|
||||
|
||||
|
||||
|
||||
//================//
|
||||
// group creation //
|
||||
//================//
|
||||
|
||||
@Override
|
||||
public IDhApiRenderableBoxGroup createForSingleBox(String resourceLocation, DhApiRenderableBox box)
|
||||
{
|
||||
ArrayList<DhApiRenderableBox> list = new ArrayList<>();
|
||||
list.add(box);
|
||||
return this.createAbsolutePositionedGroup(resourceLocation, list);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IDhApiRenderableBoxGroup createRelativePositionedGroup(String resourceLocation, DhApiVec3d originBlockPos, List<DhApiRenderableBox> boxList)
|
||||
{ return new RenderableBoxGroup(resourceLocation, new DhApiVec3d(originBlockPos.x, originBlockPos.y, originBlockPos.z), boxList, true); }
|
||||
|
||||
@Override
|
||||
public IDhApiRenderableBoxGroup createAbsolutePositionedGroup(String resourceLocation, List<DhApiRenderableBox> boxList)
|
||||
{ return new RenderableBoxGroup(resourceLocation, new DhApiVec3d(0, 0, 0), boxList, false); }
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user