Merge branch 'render_test' into 'main'
Merge the Render test branch with improvements See merge request jeseibel/distant-horizons-core!4
This commit is contained in:
@@ -19,148 +19,46 @@
|
||||
|
||||
package com.seibel.lod.core.builders.bufferBuilding;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.seibel.lod.core.enums.LodDirection;
|
||||
import com.seibel.lod.core.enums.rendering.DebugMode;
|
||||
import com.seibel.lod.core.objects.VertexOptimizer;
|
||||
import com.seibel.lod.core.objects.opengl.LodBufferBuilder;
|
||||
import com.seibel.lod.core.util.ColorUtil;
|
||||
import com.seibel.lod.core.objects.opengl.LodBox;
|
||||
import com.seibel.lod.core.objects.opengl.LodQuadBuilder;
|
||||
import com.seibel.lod.core.util.DataPointUtil;
|
||||
import com.seibel.lod.core.util.LevelPosUtil;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
|
||||
import static com.seibel.lod.core.builders.lodBuilding.LodBuilder.MIN_WORLD_HEIGHT;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Builds LODs as rectangular prisms.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 12-8-2021
|
||||
*/
|
||||
public class CubicLodTemplate
|
||||
{
|
||||
|
||||
public static void addLodToBuffer(LodBufferBuilder buffer, int playerX, int playerZ, long data, Map<LodDirection, long[]> adjData,
|
||||
byte detailLevel, int posX, int posZ, VertexOptimizer vertexOptimizer, DebugMode debugging, boolean[] adjShadeDisabled
|
||||
)//, int cullingRangeX, int cullingRangeZ)
|
||||
{
|
||||
if (vertexOptimizer == null)
|
||||
public class CubicLodTemplate {
|
||||
|
||||
public static void addLodToBuffer(long data, long topData, long botData, long[][] adjData, byte detailLevel,
|
||||
int offsetPosX, int offsetOosZ, LodQuadBuilder quadBuilder, DebugMode debugging) {
|
||||
short width = (short) (1 << detailLevel);
|
||||
short x = (short) LevelPosUtil.convert(detailLevel, offsetPosX, LodUtil.BLOCK_DETAIL_LEVEL);
|
||||
short y = DataPointUtil.getDepth(data);
|
||||
short z = (short) LevelPosUtil.convert(detailLevel, offsetOosZ, LodUtil.BLOCK_DETAIL_LEVEL);
|
||||
short dy = (short) (DataPointUtil.getHeight(data) - y);
|
||||
if (dy == 0)
|
||||
return;
|
||||
|
||||
// equivalent to 2^detailLevel
|
||||
int blockWidth = 1 << detailLevel;
|
||||
|
||||
|
||||
int color;
|
||||
if (debugging != DebugMode.OFF && debugging != DebugMode.SHOW_WIREFRAME)
|
||||
{
|
||||
if (debugging != DebugMode.OFF && debugging != DebugMode.SHOW_WIREFRAME) {
|
||||
if (debugging == DebugMode.SHOW_DETAIL || debugging == DebugMode.SHOW_DETAIL_WIREFRAME)
|
||||
color = LodUtil.DEBUG_DETAIL_LEVEL_COLORS[detailLevel].getRGB();
|
||||
else ///if (debugging == DebugMode.SHOW_GENMODE || debugging == DebugMode.SHOW_GENMODE_WIREFRAME)
|
||||
else /// if (debugging == DebugMode.SHOW_GENMODE || debugging ==
|
||||
/// DebugMode.SHOW_GENMODE_WIREFRAME)
|
||||
color = LodUtil.DEBUG_DETAIL_LEVEL_COLORS[DataPointUtil.getGenerationMode(data)].getRGB();
|
||||
}
|
||||
else
|
||||
} else
|
||||
color = DataPointUtil.getColor(data);
|
||||
|
||||
|
||||
generateBoundingBox(
|
||||
vertexOptimizer,
|
||||
DataPointUtil.getHeight(data),
|
||||
DataPointUtil.getDepth(data),
|
||||
blockWidth,
|
||||
posX * blockWidth, 0, posZ * blockWidth, // x, y, z offset
|
||||
playerX,
|
||||
playerZ,
|
||||
adjData,
|
||||
color,
|
||||
DataPointUtil.getLightSky(data),
|
||||
DataPointUtil.getLightBlock(data),
|
||||
adjShadeDisabled);
|
||||
|
||||
addBoundingBoxToBuffer(buffer, vertexOptimizer);//, cullingRangeX, cullingRangeZ);
|
||||
|
||||
LodBox.addBoxQuadsToBuilder(quadBuilder, // buffer
|
||||
width, dy, width, // setWidth
|
||||
x, y, z, // setOffset
|
||||
color, // setColor
|
||||
DataPointUtil.getLightSky(data), DataPointUtil.getLightBlock(data), // setLights
|
||||
topData, botData, adjData); // setAdjData
|
||||
}
|
||||
|
||||
/** add the given position and color to the buffer */
|
||||
public static void addPosAndColor(LodBufferBuilder buffer,
|
||||
float x, float y, float z,
|
||||
int color, byte skyLightValue, byte blockLightValue)
|
||||
{
|
||||
// TODO transparency re-add by replacing the color 255 with "ColorUtil.getAlpha(color)"
|
||||
buffer.position(x, y, z)
|
||||
.color(ColorUtil.getRed(color), ColorUtil.getGreen(color), ColorUtil.getBlue(color), 255)
|
||||
.minecraftLightValue(skyLightValue).minecraftLightValue(blockLightValue)
|
||||
.endVertex();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static void generateBoundingBox(VertexOptimizer vertexOptimizer,
|
||||
int height, int depth, int width,
|
||||
double xOffset, double yOffset, double zOffset,
|
||||
int playerX, int playerZ,
|
||||
Map<LodDirection, long[]> adjData,
|
||||
int color, byte skyLight, byte blockLight,
|
||||
boolean[] adjShadeDisabled)
|
||||
{
|
||||
// don't add an LOD if it is empty
|
||||
if (height == -1 && depth == -1)
|
||||
return;
|
||||
|
||||
if (depth == height)
|
||||
// if the top and bottom points are at the same height
|
||||
// render this LOD as 1 block thick
|
||||
height++;
|
||||
|
||||
// offset the AABB by its x/z position in the world since
|
||||
// it uses doubles to specify its location, unlike the model view matrix
|
||||
// which only uses floats
|
||||
double x = -playerX;
|
||||
double z = -playerZ;
|
||||
vertexOptimizer.reset();
|
||||
vertexOptimizer.setColor(color, adjShadeDisabled);
|
||||
vertexOptimizer.setLights(skyLight, blockLight);
|
||||
vertexOptimizer.setWidth(width, height - depth, width);
|
||||
vertexOptimizer.setOffset((int) (xOffset + x), (int) (depth + yOffset), (int) (zOffset + z));
|
||||
vertexOptimizer.setAdjData(adjData);
|
||||
}
|
||||
|
||||
private static void addBoundingBoxToBuffer(LodBufferBuilder buffer, VertexOptimizer vertexOptimizer)//, int cullingRangeX, int cullingRangeZ)
|
||||
{
|
||||
int color;
|
||||
byte skyLight;
|
||||
byte blockLight;
|
||||
|
||||
for (LodDirection lodDirection : VertexOptimizer.DIRECTIONS)
|
||||
{
|
||||
//if(vertexOptimizer.isCulled(lodDirection))
|
||||
// continue;
|
||||
// culling
|
||||
// FIXME: Reimpl backface culling
|
||||
/*
|
||||
if (lodDirection == LodDirection.NORTH && vertexOptimizer.getZ(lodDirection, 0) < -cullingRangeZ
|
||||
|| lodDirection == LodDirection.EAST && vertexOptimizer.getX(lodDirection, 0) > cullingRangeX
|
||||
|| lodDirection == LodDirection.SOUTH && vertexOptimizer.getZ(lodDirection, 0) > cullingRangeZ
|
||||
|| lodDirection == LodDirection.WEST && vertexOptimizer.getX(lodDirection, 0) < -cullingRangeX)
|
||||
continue;
|
||||
*/
|
||||
|
||||
int verticalFaceIndex = 0;
|
||||
while (vertexOptimizer.shouldRenderFace(lodDirection, verticalFaceIndex))
|
||||
{
|
||||
for (int vertexIndex = 0; vertexIndex < 6; vertexIndex++)
|
||||
{
|
||||
skyLight = vertexOptimizer.getSkyLight(lodDirection, verticalFaceIndex);
|
||||
blockLight = (byte) vertexOptimizer.getBlockLight();
|
||||
color = vertexOptimizer.getColor(lodDirection);
|
||||
addPosAndColor(buffer,
|
||||
vertexOptimizer.getX(lodDirection, vertexIndex),
|
||||
vertexOptimizer.getY(lodDirection, vertexIndex, verticalFaceIndex) + MIN_WORLD_HEIGHT,
|
||||
vertexOptimizer.getZ(lodDirection, vertexIndex),
|
||||
color, skyLight, blockLight );
|
||||
}
|
||||
verticalFaceIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+375
-510
File diff suppressed because it is too large
Load Diff
@@ -23,7 +23,20 @@ public enum LodDirection
|
||||
SOUTH(3, 2, 0, "south", LodDirection.AxisDirection.POSITIVE, LodDirection.Axis.Z, new Vec3i(0, 0, 1)),
|
||||
WEST(4, 5, 1, "west", LodDirection.AxisDirection.NEGATIVE, LodDirection.Axis.X, new Vec3i(-1, 0, 0)),
|
||||
EAST(5, 4, 3, "east", LodDirection.AxisDirection.POSITIVE, LodDirection.Axis.X, new Vec3i(1, 0, 0));
|
||||
|
||||
public static final LodDirection[] DIRECTIONS = new LodDirection[] {
|
||||
LodDirection.UP,
|
||||
LodDirection.DOWN,
|
||||
LodDirection.WEST,
|
||||
LodDirection.EAST,
|
||||
LodDirection.NORTH,
|
||||
LodDirection.SOUTH };
|
||||
|
||||
/** North, South, East, West */
|
||||
public static final LodDirection[] ADJ_DIRECTIONS = new LodDirection[] {
|
||||
LodDirection.EAST,
|
||||
LodDirection.WEST,
|
||||
LodDirection.SOUTH,
|
||||
LodDirection.NORTH };
|
||||
// private final int data3d;
|
||||
// private final int oppositeIndex;
|
||||
// private final int data2d;
|
||||
|
||||
@@ -1,591 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
|
||||
* licensed under the GNU GPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.core.objects;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.seibel.lod.core.enums.LodDirection;
|
||||
import com.seibel.lod.core.enums.rendering.DebugMode;
|
||||
import com.seibel.lod.core.objects.math.Vec3i;
|
||||
import com.seibel.lod.core.util.ColorUtil;
|
||||
import com.seibel.lod.core.util.DataPointUtil;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.util.SingletonHandler;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
|
||||
|
||||
/**
|
||||
* This class handles all the vertex optimization that's needed for a column of lods. W
|
||||
* @author Leonardo Amato
|
||||
* @version 10-2-2021
|
||||
*/
|
||||
public class VertexOptimizer
|
||||
{
|
||||
private static final IMinecraftWrapper MC = SingletonHandler.get(IMinecraftWrapper.class);
|
||||
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
|
||||
|
||||
public static final int ADJACENT_HEIGHT_INDEX = 0;
|
||||
public static final int ADJACENT_DEPTH_INDEX = 1;
|
||||
|
||||
public static final int X = 0;
|
||||
public static final int Y = 1;
|
||||
public static final int Z = 2;
|
||||
|
||||
public static final int MIN = 0;
|
||||
public static final int MAX = 1;
|
||||
|
||||
public static final int VOID_FACE = 0;
|
||||
|
||||
/** The six cardinal directions */
|
||||
public static final LodDirection[] DIRECTIONS = new LodDirection[] {
|
||||
LodDirection.UP,
|
||||
LodDirection.DOWN,
|
||||
LodDirection.WEST,
|
||||
LodDirection.EAST,
|
||||
LodDirection.NORTH,
|
||||
LodDirection.SOUTH };
|
||||
|
||||
/** North, South, East, West */
|
||||
public static final LodDirection[] ADJ_DIRECTIONS = new LodDirection[] {
|
||||
LodDirection.EAST,
|
||||
LodDirection.WEST,
|
||||
LodDirection.SOUTH,
|
||||
LodDirection.NORTH };
|
||||
|
||||
/** All the faces and vertices of a cube. This is used to extract the vertex from the column */
|
||||
@SuppressWarnings("serial")
|
||||
public static final Map<LodDirection, int[][]> DIRECTION_VERTEX_MAP = new HashMap<LodDirection, int[][]>()
|
||||
{{
|
||||
put(LodDirection.UP, new int[][] {
|
||||
{ 0, 1, 0 }, // 0
|
||||
{ 0, 1, 1 }, // 1
|
||||
{ 1, 1, 1 }, // 2
|
||||
|
||||
{ 0, 1, 0 }, // 0
|
||||
{ 1, 1, 1 }, // 2
|
||||
{ 1, 1, 0 } // 3
|
||||
});
|
||||
put(LodDirection.DOWN, new int[][] {
|
||||
{ 1, 0, 0 }, // 0
|
||||
{ 1, 0, 1 }, // 1
|
||||
{ 0, 0, 1 }, // 2
|
||||
|
||||
{ 1, 0, 0 }, // 0
|
||||
{ 0, 0, 1 }, // 2
|
||||
{ 0, 0, 0 } // 3
|
||||
});
|
||||
put(LodDirection.EAST, new int[][] {
|
||||
{ 1, 1, 0 }, // 0
|
||||
{ 1, 1, 1 }, // 1
|
||||
{ 1, 0, 1 }, // 2
|
||||
|
||||
{ 1, 1, 0 }, // 0
|
||||
{ 1, 0, 1 }, // 2
|
||||
{ 1, 0, 0 } }); // 3
|
||||
put(LodDirection.WEST, new int[][] {
|
||||
{ 0, 0, 0 }, // 0
|
||||
{ 0, 0, 1 }, // 1
|
||||
{ 0, 1, 1 }, // 2
|
||||
|
||||
{ 0, 0, 0 }, // 0
|
||||
{ 0, 1, 1 }, // 2
|
||||
{ 0, 1, 0 } // 3
|
||||
});
|
||||
put(LodDirection.SOUTH, new int[][] {
|
||||
{ 1, 0, 1 }, // 0
|
||||
{ 1, 1, 1 }, // 1
|
||||
{ 0, 1, 1 }, // 2
|
||||
|
||||
{ 1, 0, 1 }, // 0
|
||||
{ 0, 1, 1 }, // 2
|
||||
{ 0, 0, 1 } // 3
|
||||
});
|
||||
put(LodDirection.NORTH, new int[][] {
|
||||
{ 0, 0, 0 }, // 0
|
||||
{ 0, 1, 0 }, // 1
|
||||
{ 1, 1, 0 }, // 2
|
||||
|
||||
{ 0, 0, 0 }, // 0
|
||||
{ 1, 1, 0 }, // 2
|
||||
{ 1, 0, 0 } // 3
|
||||
});
|
||||
}};
|
||||
|
||||
|
||||
/**
|
||||
* This indicates which position is invariable in the DIRECTION_VERTEX_MAP.
|
||||
* Is used to extract the vertex
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public static final Map<LodDirection, int[]> FACE_DIRECTION = new HashMap<LodDirection, int[]>()
|
||||
{{
|
||||
put(LodDirection.UP, new int[] { Y, MAX });
|
||||
put(LodDirection.DOWN, new int[] { Y, MIN });
|
||||
put(LodDirection.EAST, new int[] { X, MAX });
|
||||
put(LodDirection.WEST, new int[] { X, MIN });
|
||||
put(LodDirection.SOUTH, new int[] { Z, MAX });
|
||||
put(LodDirection.NORTH, new int[] { Z, MIN });
|
||||
}};
|
||||
|
||||
|
||||
/**
|
||||
* This is a map from Direction to the relative normal vector
|
||||
* we are using this since I'm not sure if the getNormal create new object at every call
|
||||
*/
|
||||
// FIXME: No. It doesn't. Just remove this.
|
||||
@SuppressWarnings("serial")
|
||||
public static final Map<LodDirection, Vec3i> DIRECTION_NORMAL_MAP = new HashMap<LodDirection, Vec3i>()
|
||||
{{
|
||||
put(LodDirection.UP, LodDirection.UP.getNormal());
|
||||
put(LodDirection.DOWN, LodDirection.DOWN.getNormal());
|
||||
put(LodDirection.EAST, LodDirection.EAST.getNormal());
|
||||
put(LodDirection.WEST, LodDirection.WEST.getNormal());
|
||||
put(LodDirection.SOUTH, LodDirection.SOUTH.getNormal());
|
||||
put(LodDirection.NORTH, LodDirection.NORTH.getNormal());
|
||||
}};
|
||||
|
||||
/** We use this index for all array that are going to */
|
||||
@SuppressWarnings("serial")
|
||||
public static final Map<LodDirection, Integer> DIRECTION_INDEX = new HashMap<LodDirection, Integer>()
|
||||
{{
|
||||
put(LodDirection.UP, 0);
|
||||
put(LodDirection.DOWN, 1);
|
||||
put(LodDirection.EAST, 2);
|
||||
put(LodDirection.WEST, 3);
|
||||
put(LodDirection.SOUTH, 4);
|
||||
put(LodDirection.NORTH, 5);
|
||||
}};
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public static final Map<LodDirection, Integer> ADJ_DIRECTION_INDEX = new HashMap<LodDirection, Integer>()
|
||||
{{
|
||||
put(LodDirection.EAST, 0);
|
||||
put(LodDirection.WEST, 1);
|
||||
put(LodDirection.SOUTH, 2);
|
||||
put(LodDirection.NORTH, 3);
|
||||
}};
|
||||
/** holds the box's x, y, z offset */
|
||||
public final int[] boxOffset;
|
||||
/** holds the box's x, y, z width */
|
||||
public final int[] boxWidth;
|
||||
|
||||
/** Holds each direction's color */
|
||||
public final int[] colorMap;
|
||||
/** The original color (before shading) of this box */
|
||||
public int color;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public final Map<LodDirection, int[]> adjHeight;
|
||||
public final Map<LodDirection, int[]> adjDepth;
|
||||
public final Map<LodDirection, byte[]> skyLights;
|
||||
public byte blockLight;
|
||||
|
||||
boolean skipTop;
|
||||
boolean skipBot;
|
||||
|
||||
|
||||
|
||||
/** creates an empty box */
|
||||
@SuppressWarnings("serial")
|
||||
public VertexOptimizer()
|
||||
{
|
||||
boxOffset = new int[3];
|
||||
boxWidth = new int[3];
|
||||
|
||||
colorMap = new int[6];
|
||||
skyLights = new HashMap<LodDirection, byte[]>()
|
||||
{{
|
||||
put(LodDirection.UP, new byte[1]);
|
||||
put(LodDirection.DOWN, new byte[1]);
|
||||
put(LodDirection.EAST, new byte[LodUtil.MAX_NUMBER_OF_VERTICAL_LODS]);
|
||||
put(LodDirection.WEST, new byte[LodUtil.MAX_NUMBER_OF_VERTICAL_LODS]);
|
||||
put(LodDirection.SOUTH, new byte[LodUtil.MAX_NUMBER_OF_VERTICAL_LODS]);
|
||||
put(LodDirection.NORTH, new byte[LodUtil.MAX_NUMBER_OF_VERTICAL_LODS]);
|
||||
}};
|
||||
adjHeight = new HashMap<LodDirection, int[]>()
|
||||
{{
|
||||
put(LodDirection.EAST, new int[LodUtil.MAX_NUMBER_OF_VERTICAL_LODS]);
|
||||
put(LodDirection.WEST, new int[LodUtil.MAX_NUMBER_OF_VERTICAL_LODS]);
|
||||
put(LodDirection.SOUTH, new int[LodUtil.MAX_NUMBER_OF_VERTICAL_LODS]);
|
||||
put(LodDirection.NORTH, new int[LodUtil.MAX_NUMBER_OF_VERTICAL_LODS]);
|
||||
}};
|
||||
adjDepth = new HashMap<LodDirection, int[]>()
|
||||
{{
|
||||
put(LodDirection.EAST, new int[LodUtil.MAX_NUMBER_OF_VERTICAL_LODS]);
|
||||
put(LodDirection.WEST, new int[LodUtil.MAX_NUMBER_OF_VERTICAL_LODS]);
|
||||
put(LodDirection.SOUTH, new int[LodUtil.MAX_NUMBER_OF_VERTICAL_LODS]);
|
||||
put(LodDirection.NORTH, new int[LodUtil.MAX_NUMBER_OF_VERTICAL_LODS]);
|
||||
}};
|
||||
}
|
||||
|
||||
/** Set the light of the columns */
|
||||
public void setLights(int skyLight, int blockLight)
|
||||
{
|
||||
this.blockLight = (byte) blockLight;
|
||||
skyLights.get(LodDirection.UP)[0] = (byte) skyLight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the color of the columns
|
||||
* @param color color to add
|
||||
* @param adjShadeDisabled this array indicates which face does not need shading
|
||||
*/
|
||||
public void setColor(int color, boolean[] adjShadeDisabled)
|
||||
{
|
||||
this.color = color;
|
||||
for (LodDirection lodDirection : DIRECTIONS)
|
||||
{
|
||||
if (!adjShadeDisabled[DIRECTION_INDEX.get(lodDirection)])
|
||||
colorMap[DIRECTION_INDEX.get(lodDirection)] = ColorUtil.applyShade(color, MC.getShade(lodDirection));
|
||||
else
|
||||
colorMap[DIRECTION_INDEX.get(lodDirection)] = color;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param lodDirection of the face of which we want to get the color
|
||||
* @return color of the face
|
||||
*/
|
||||
public int getColor(LodDirection lodDirection)
|
||||
{
|
||||
if (CONFIG.client().advanced().debugging().getDebugMode() != DebugMode.SHOW_DETAIL &&
|
||||
CONFIG.client().advanced().debugging().getDebugMode() != DebugMode.SHOW_WIREFRAME)
|
||||
return colorMap[DIRECTION_INDEX.get(lodDirection)];
|
||||
else
|
||||
return ColorUtil.applyShade(color, MC.getShade(lodDirection));
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public byte getSkyLight(LodDirection lodDirection, int verticalIndex)
|
||||
{
|
||||
if(lodDirection == LodDirection.UP || lodDirection == LodDirection.DOWN)
|
||||
return skyLights.get(lodDirection)[0];
|
||||
else
|
||||
return skyLights.get(lodDirection)[verticalIndex];
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
public int getBlockLight()
|
||||
{
|
||||
return blockLight;
|
||||
}
|
||||
/** clears this box, resetting everything to default values */
|
||||
public void reset()
|
||||
{
|
||||
Arrays.fill(boxWidth, 0);
|
||||
Arrays.fill(boxOffset, 0);
|
||||
Arrays.fill(colorMap, 0);
|
||||
blockLight = 0;
|
||||
for (LodDirection lodDirection : ADJ_DIRECTIONS)
|
||||
{
|
||||
for (int i = 0; i < adjHeight.get(lodDirection).length; i++)
|
||||
{
|
||||
adjHeight.get(lodDirection)[i] = VOID_FACE;
|
||||
adjDepth.get(lodDirection)[i] = VOID_FACE;
|
||||
skyLights.get(lodDirection)[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This method create all the shared face culling based on the adjacent data
|
||||
* @param adjData data adjacent to the column we are going to render
|
||||
*/
|
||||
public void setAdjData(Map<LodDirection, long[]> adjData)
|
||||
{
|
||||
int height;
|
||||
int depth;
|
||||
int minY = getMinY();
|
||||
int maxY = getMaxY();
|
||||
long singleAdjDataPoint;
|
||||
|
||||
// TODO transparency uncomment final condition to see ocean floor
|
||||
//Up direction case
|
||||
singleAdjDataPoint = adjData.get(LodDirection.UP)[0];
|
||||
skipTop = DataPointUtil.doesItExist(singleAdjDataPoint) && DataPointUtil.getDepth(singleAdjDataPoint) == maxY;// && DataPointUtil.getAlpha(singleAdjDataPoint) == 255;
|
||||
//Down direction case
|
||||
singleAdjDataPoint = adjData.get(LodDirection.DOWN)[0];
|
||||
skipBot = DataPointUtil.doesItExist(singleAdjDataPoint) && DataPointUtil.getHeight(singleAdjDataPoint) == minY;// && DataPointUtil.getAlpha(singleAdjDataPoint) == 255;
|
||||
if(DataPointUtil.doesItExist(singleAdjDataPoint))
|
||||
skyLights.get(LodDirection.DOWN)[0] = DataPointUtil.getLightSky(singleAdjDataPoint);
|
||||
else
|
||||
skyLights.get(LodDirection.DOWN)[0] = skyLights.get(LodDirection.UP)[0];
|
||||
//other sided
|
||||
//TODO clean some similar cases
|
||||
for (LodDirection lodDirection : ADJ_DIRECTIONS)
|
||||
{
|
||||
long[] dataPoint = adjData.get(lodDirection);
|
||||
if (dataPoint == null || DataPointUtil.isVoid(dataPoint[0]))
|
||||
{
|
||||
adjHeight.get(lodDirection)[0] = maxY;
|
||||
adjDepth.get(lodDirection)[0] = minY;
|
||||
adjHeight.get(lodDirection)[1] = VOID_FACE;
|
||||
adjDepth.get(lodDirection)[1] = VOID_FACE;
|
||||
skyLights.get(lodDirection)[0] = 15; //in void set full skylight
|
||||
continue;
|
||||
}
|
||||
|
||||
int i;
|
||||
int faceToDraw = 0;
|
||||
boolean firstFace = true;
|
||||
boolean toFinish = false;
|
||||
int toFinishIndex = 0;
|
||||
boolean allAbove = true;
|
||||
// TODO transparency ocean floor fix
|
||||
//boolean isOpaque = ((colorMap[0] >> 24) & 0xFF) == 255;
|
||||
for (i = 0; i < dataPoint.length; i++)
|
||||
{
|
||||
singleAdjDataPoint = dataPoint[i];
|
||||
if (DataPointUtil.isVoid(singleAdjDataPoint) || !DataPointUtil.doesItExist(singleAdjDataPoint))
|
||||
break;
|
||||
|
||||
// TODO transparency ocean floor fix
|
||||
//if (isOpaque && DataPointUtil.getAlpha(singleAdjDataPoint) != 255)
|
||||
// continue;
|
||||
|
||||
height = DataPointUtil.getHeight(singleAdjDataPoint);
|
||||
depth = DataPointUtil.getDepth(singleAdjDataPoint);
|
||||
|
||||
if (depth < maxY)
|
||||
{
|
||||
allAbove = false;
|
||||
if (height < minY)
|
||||
{
|
||||
// the adj data is lower than the current data
|
||||
|
||||
if (firstFace)
|
||||
{
|
||||
adjHeight.get(lodDirection)[0] = getMaxY();
|
||||
adjDepth.get(lodDirection)[0] = getMinY();
|
||||
skyLights.get(lodDirection)[0] = DataPointUtil.getLightSky(singleAdjDataPoint); //skyLights.get(Direction.UP)[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
adjDepth.get(lodDirection)[faceToDraw] = getMinY();
|
||||
skyLights.get(lodDirection)[faceToDraw] = DataPointUtil.getLightSky(singleAdjDataPoint);
|
||||
}
|
||||
faceToDraw++;
|
||||
toFinish = false;
|
||||
|
||||
// break since all the other data will be lower
|
||||
break;
|
||||
}
|
||||
else if (depth <= minY)
|
||||
{
|
||||
if (height >= maxY)
|
||||
{
|
||||
// the adj data is inside the current data
|
||||
// don't draw the face
|
||||
adjHeight.get(lodDirection)[0] = VOID_FACE;
|
||||
adjDepth.get(lodDirection)[0] = VOID_FACE;
|
||||
}
|
||||
else // height < maxY
|
||||
{
|
||||
// the adj data intersects the lower part of the current data
|
||||
// if this is the only face, use the maxY and break,
|
||||
// if there was another face we finish the last one and break
|
||||
if (firstFace)
|
||||
{
|
||||
adjHeight.get(lodDirection)[0] = getMaxY();
|
||||
adjDepth.get(lodDirection)[0] = height;
|
||||
skyLights.get(lodDirection)[0] = DataPointUtil.getLightSky(singleAdjDataPoint); //skyLights.get(Direction.UP)[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
adjDepth.get(lodDirection)[faceToDraw] = height;
|
||||
skyLights.get(lodDirection)[faceToDraw] = DataPointUtil.getLightSky(singleAdjDataPoint);
|
||||
}
|
||||
toFinish = false;
|
||||
faceToDraw++;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (height >= maxY)// && depth > minY
|
||||
{
|
||||
// the adj data intersects the higher part of the current data
|
||||
// we start the creation of a new face
|
||||
adjHeight.get(lodDirection)[faceToDraw] = depth;
|
||||
//skyLights.get(direction)[faceToDraw] = (byte) DataPointUtil.getLightSkyAlt(singleAdjDataPoint);
|
||||
firstFace = false;
|
||||
toFinish = true;
|
||||
toFinishIndex = i + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// if (depth > minY && height < maxY)
|
||||
|
||||
// the adj data is contained in the current data
|
||||
if (firstFace)
|
||||
{
|
||||
adjHeight.get(lodDirection)[0] = getMaxY();
|
||||
}
|
||||
|
||||
adjDepth.get(lodDirection)[faceToDraw] = height;
|
||||
skyLights.get(lodDirection)[faceToDraw] = DataPointUtil.getLightSky(singleAdjDataPoint);
|
||||
faceToDraw++;
|
||||
adjHeight.get(lodDirection)[faceToDraw] = depth;
|
||||
firstFace = false;
|
||||
toFinish = true;
|
||||
toFinishIndex = i + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (allAbove)
|
||||
{
|
||||
adjHeight.get(lodDirection)[0] = getMaxY();
|
||||
adjDepth.get(lodDirection)[0] = getMinY();
|
||||
skyLights.get(lodDirection)[0] = skyLights.get(LodDirection.UP)[0];
|
||||
faceToDraw++;
|
||||
}
|
||||
else if (toFinish)
|
||||
{
|
||||
adjDepth.get(lodDirection)[faceToDraw] = minY;
|
||||
if(toFinishIndex < dataPoint.length)
|
||||
{
|
||||
singleAdjDataPoint = dataPoint[toFinishIndex];
|
||||
if (DataPointUtil.doesItExist(singleAdjDataPoint))
|
||||
skyLights.get(lodDirection)[faceToDraw] = DataPointUtil.getLightSky(singleAdjDataPoint);
|
||||
else
|
||||
skyLights.get(lodDirection)[faceToDraw] = skyLights.get(LodDirection.UP)[0];
|
||||
}
|
||||
faceToDraw++;
|
||||
}
|
||||
|
||||
adjHeight.get(lodDirection)[faceToDraw] = VOID_FACE;
|
||||
adjDepth.get(lodDirection)[faceToDraw] = VOID_FACE;
|
||||
}
|
||||
}
|
||||
|
||||
/** We use this method to set the various width of the column */
|
||||
public void setWidth(int xWidth, int yWidth, int zWidth)
|
||||
{
|
||||
boxWidth[X] = xWidth;
|
||||
boxWidth[Y] = yWidth;
|
||||
boxWidth[Z] = zWidth;
|
||||
}
|
||||
|
||||
/** We use this method to set the various offset of the column */
|
||||
public void setOffset(int xOffset, int yOffset, int zOffset)
|
||||
{
|
||||
boxOffset[X] = xOffset;
|
||||
boxOffset[Y] = yOffset;
|
||||
boxOffset[Z] = zOffset;
|
||||
}
|
||||
|
||||
/** returns true if the given direction should be rendered. */
|
||||
public boolean shouldRenderFace(LodDirection lodDirection, int adjIndex)
|
||||
{
|
||||
if (lodDirection == LodDirection.UP)
|
||||
return adjIndex == 0 && !skipTop;
|
||||
if (lodDirection == LodDirection.DOWN)
|
||||
return adjIndex == 0 && !skipBot;
|
||||
|
||||
return !(adjHeight.get(lodDirection)[adjIndex] == VOID_FACE && adjDepth.get(lodDirection)[adjIndex] == VOID_FACE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param lodDirection direction of the face we want to render
|
||||
* @param vertexIndex index of the vertex of the face (0-1-2-3)
|
||||
* @return position x of the relative vertex
|
||||
*/
|
||||
public int getX(LodDirection lodDirection, int vertexIndex)
|
||||
{
|
||||
return boxOffset[X] + boxWidth[X] * DIRECTION_VERTEX_MAP.get(lodDirection)[vertexIndex][X];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param lodDirection direction of the face we want to render
|
||||
* @param vertexIndex index of the vertex of the face (0-1-2-3)
|
||||
* @return position y of the relative vertex
|
||||
*/
|
||||
public int getY(LodDirection lodDirection, int vertexIndex)
|
||||
{
|
||||
return boxOffset[Y] + boxWidth[Y] * DIRECTION_VERTEX_MAP.get(lodDirection)[vertexIndex][Y];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param lodDirection direction of the face we want to render
|
||||
* @param vertexIndex index of the vertex of the face (0-1-2-3)
|
||||
* @param adjIndex, index of the n-th culled face of this direction
|
||||
* @return position x of the relative vertex
|
||||
*/
|
||||
public int getY(LodDirection lodDirection, int vertexIndex, int adjIndex)
|
||||
{
|
||||
if (lodDirection == LodDirection.DOWN || lodDirection == LodDirection.UP)
|
||||
return boxOffset[Y] + boxWidth[Y] * DIRECTION_VERTEX_MAP.get(lodDirection)[vertexIndex][Y];
|
||||
else
|
||||
{
|
||||
// this could probably be cleaned up more,
|
||||
// but it still works
|
||||
if (1 - DIRECTION_VERTEX_MAP.get(lodDirection)[vertexIndex][Y] == ADJACENT_HEIGHT_INDEX)
|
||||
return adjHeight.get(lodDirection)[adjIndex];
|
||||
else
|
||||
return adjDepth.get(lodDirection)[adjIndex];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param lodDirection direction of the face we want to render
|
||||
* @param vertexIndex index of the vertex of the face (0-1-2-3)
|
||||
* @return position z of the relative vertex
|
||||
*/
|
||||
public int getZ(LodDirection lodDirection, int vertexIndex)
|
||||
{
|
||||
return boxOffset[Z] + boxWidth[Z] * DIRECTION_VERTEX_MAP.get(lodDirection)[vertexIndex][Z];
|
||||
}
|
||||
|
||||
public int getMinX()
|
||||
{
|
||||
return boxOffset[X];
|
||||
}
|
||||
|
||||
public int getMaxX()
|
||||
{
|
||||
return boxOffset[X] + boxWidth[X];
|
||||
}
|
||||
|
||||
public int getMinY()
|
||||
{
|
||||
return boxOffset[Y];
|
||||
}
|
||||
|
||||
public int getMaxY()
|
||||
{
|
||||
return boxOffset[Y] + boxWidth[Y];
|
||||
}
|
||||
|
||||
public int getMinZ()
|
||||
{
|
||||
return boxOffset[Z];
|
||||
}
|
||||
|
||||
public int getMaxZ()
|
||||
{
|
||||
return boxOffset[Z] + boxWidth[Z];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -68,6 +68,14 @@ public interface LevelContainer
|
||||
* @return the data in long array format
|
||||
*/
|
||||
long getData(int posX, int posZ, int index);
|
||||
|
||||
/**
|
||||
* With this you can get data from the level container
|
||||
* @param posX x position in the detail level
|
||||
* @param posZ z position in the detail level
|
||||
* @return the data in long array format
|
||||
*/
|
||||
long[] getAllData(int posX, int posZ);
|
||||
|
||||
/**
|
||||
* With this you can get data from the level container
|
||||
|
||||
@@ -550,6 +550,25 @@ public class LodDimension
|
||||
return region.getData(detailLevel, posX, posZ, verticalIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the data point at the given X and Z coordinates
|
||||
* in this dimension.
|
||||
* <br>
|
||||
* Returns null if the LodChunk doesn't exist or
|
||||
* is outside the loaded area.
|
||||
*/
|
||||
public long[] getAllData(byte detailLevel, int posX, int posZ)
|
||||
{
|
||||
if (detailLevel > LodUtil.REGION_DETAIL_LEVEL)
|
||||
throw new IllegalArgumentException("getLodFromCoordinates given a level of \"" + detailLevel + "\" when \"" + LodUtil.REGION_DETAIL_LEVEL + "\" is the max.");
|
||||
|
||||
LodRegion region = getRegion(detailLevel, posX, posZ);
|
||||
if (region == null)
|
||||
return null;
|
||||
|
||||
return region.getAllData(detailLevel, posX, posZ);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the data point at the given X and Z coordinates
|
||||
|
||||
@@ -190,6 +190,18 @@ public class LodRegion {
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
return dataContainer[detailLevel].getData(posX, posZ, verticalIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the dataPoint at the given relative position.
|
||||
*
|
||||
* @return the data at the relative pos and detail level, 0 if the data doesn't
|
||||
* exist.
|
||||
*/
|
||||
public long[] getAllData(byte detailLevel, int posX, int posZ) {
|
||||
posX = LevelPosUtil.getRegionModule(detailLevel, posX);
|
||||
posZ = LevelPosUtil.getRegionModule(detailLevel, posZ);
|
||||
return dataContainer[detailLevel].getAllData(posX, posZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the dataPoint at the given relative position.
|
||||
|
||||
@@ -26,8 +26,6 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.Arrays;
|
||||
|
||||
import com.seibel.lod.core.dataFormat.*;
|
||||
import com.seibel.lod.core.enums.config.DistanceGenerationMode;
|
||||
import com.seibel.lod.core.util.*;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
|
||||
|
||||
@@ -188,6 +186,15 @@ public class VerticalLevelContainer implements LevelContainer
|
||||
return dataContainer[posX * size * verticalSize + posZ * verticalSize];
|
||||
}
|
||||
|
||||
@Override
|
||||
public long[] getAllData(int posX, int posZ)
|
||||
{
|
||||
long[] result = new long[verticalSize];
|
||||
int index = posX * size * verticalSize + posZ * verticalSize;
|
||||
System.arraycopy(dataContainer, index, result, 0, verticalSize);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getVerticalSize()
|
||||
{
|
||||
|
||||
@@ -397,6 +397,7 @@ public class Mat4f
|
||||
/**
|
||||
* 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)
|
||||
{
|
||||
|
||||
@@ -30,14 +30,14 @@ import com.google.common.collect.ImmutableList;
|
||||
*/
|
||||
public class DefaultLodVertexFormats
|
||||
{
|
||||
public static final LodVertexFormatElement ELEMENT_POSITION = new LodVertexFormatElement(0, LodVertexFormatElement.DataType.FLOAT, 3, false);
|
||||
public static final LodVertexFormatElement ELEMENT_POSITION = new LodVertexFormatElement(3, LodVertexFormatElement.DataType.USHORT, 3, false);
|
||||
public static final LodVertexFormatElement ELEMENT_COLOR = new LodVertexFormatElement(0, LodVertexFormatElement.DataType.UBYTE, 4, false);
|
||||
public static final LodVertexFormatElement ELEMENT_UV = new LodVertexFormatElement(0, LodVertexFormatElement.DataType.FLOAT, 2, false);
|
||||
public static final LodVertexFormatElement ELEMENT_LIGHT_MAP_UV = new LodVertexFormatElement(1, LodVertexFormatElement.DataType.SHORT, 2, false);
|
||||
public static final LodVertexFormatElement ELEMENT_NORMAL = new LodVertexFormatElement(0, LodVertexFormatElement.DataType.BYTE, 3, false);
|
||||
public static final LodVertexFormatElement ELEMENT_PADDING = new LodVertexFormatElement(0, LodVertexFormatElement.DataType.BYTE, 1, true);
|
||||
|
||||
public static final LodVertexFormatElement ELEMENT_BLOCK_LIGHT = new LodVertexFormatElement(0, LodVertexFormatElement.DataType.UBYTE, 1, false);
|
||||
public static final LodVertexFormatElement ELEMENT_LIGHT = new LodVertexFormatElement(0, LodVertexFormatElement.DataType.UBYTE, 1, false);
|
||||
|
||||
|
||||
public static final LodVertexFormat POSITION = new LodVertexFormat(ImmutableList.<LodVertexFormatElement>builder().add(ELEMENT_POSITION).build());
|
||||
@@ -47,5 +47,7 @@ public class DefaultLodVertexFormats
|
||||
public static final LodVertexFormat POSITION_COLOR_TEX = new LodVertexFormat(ImmutableList.<LodVertexFormatElement>builder().add(ELEMENT_POSITION).add(ELEMENT_COLOR).add(ELEMENT_UV).build());
|
||||
public static final LodVertexFormat POSITION_COLOR_TEX_LIGHTMAP = new LodVertexFormat(ImmutableList.<LodVertexFormatElement>builder().add(ELEMENT_POSITION).add(ELEMENT_COLOR).add(ELEMENT_UV).add(ELEMENT_LIGHT_MAP_UV).build());
|
||||
|
||||
public static final LodVertexFormat POSITION_COLOR_BLOCK_LIGHT_SKY_LIGHT = new LodVertexFormat(ImmutableList.<LodVertexFormatElement>builder().add(ELEMENT_POSITION).add(ELEMENT_COLOR).add(ELEMENT_BLOCK_LIGHT).add(ELEMENT_BLOCK_LIGHT).add(ELEMENT_PADDING).add(ELEMENT_PADDING).build());
|
||||
public static final LodVertexFormat POSITION_COLOR_BLOCK_LIGHT_SKY_LIGHT = new LodVertexFormat(ImmutableList.<LodVertexFormatElement>builder()
|
||||
.add(ELEMENT_POSITION).add(ELEMENT_PADDING).add(ELEMENT_LIGHT)
|
||||
.add(ELEMENT_COLOR).build());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,161 @@
|
||||
package com.seibel.lod.core.objects.opengl;
|
||||
|
||||
import com.seibel.lod.core.enums.LodDirection;
|
||||
import com.seibel.lod.core.util.ColorUtil;
|
||||
import com.seibel.lod.core.util.DataPointUtil;
|
||||
import com.seibel.lod.core.util.SingletonHandler;
|
||||
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftWrapper;
|
||||
|
||||
public class LodBox {
|
||||
private static final IMinecraftWrapper MC = SingletonHandler.get(IMinecraftWrapper.class);
|
||||
|
||||
public static void addBoxQuadsToBuilder(LodQuadBuilder builder, short xSize, short ySize, short zSize, short x,
|
||||
short y, short z, int color, byte skyLight, byte blockLight, long topData, long botData, long[][] adjData) {
|
||||
short maxX = (short) (x + xSize);
|
||||
short maxY = (short) (y + ySize);
|
||||
short maxZ = (short) (z + zSize);
|
||||
byte skyLightTop = skyLight;
|
||||
byte skyLightBot = DataPointUtil.doesItExist(botData) ? DataPointUtil.getLightSky(botData) : 0;
|
||||
|
||||
// Up direction case
|
||||
boolean skipTop = DataPointUtil.doesItExist(topData) && DataPointUtil.getDepth(topData) == maxY;// &&
|
||||
// DataPointUtil.getAlpha(singleAdjDataPoint)
|
||||
// == 255;
|
||||
boolean skipBot = DataPointUtil.doesItExist(botData) && DataPointUtil.getHeight(botData) == y;// &&
|
||||
// DataPointUtil.getAlpha(singleAdjDataPoint)
|
||||
// == 255;
|
||||
|
||||
if (!skipTop)
|
||||
builder.addQuadUp(x, maxY, z, xSize, zSize, color, skyLightTop, blockLight);
|
||||
if (!skipBot)
|
||||
builder.addQuadDown(x, y, z, xSize, zSize, color, skyLightBot, blockLight);
|
||||
makeAdjQuads(builder, adjData[LodDirection.NORTH.ordinal() - 2], LodDirection.NORTH, x, y, z, xSize, ySize,
|
||||
color, skyLightTop, blockLight);
|
||||
makeAdjQuads(builder, adjData[LodDirection.SOUTH.ordinal() - 2], LodDirection.SOUTH, x, y, maxZ, xSize, ySize,
|
||||
color, skyLightTop, blockLight);
|
||||
makeAdjQuads(builder, adjData[LodDirection.WEST.ordinal() - 2], LodDirection.WEST, x, y, z, zSize, ySize, color,
|
||||
skyLightTop, blockLight);
|
||||
makeAdjQuads(builder, adjData[LodDirection.EAST.ordinal() - 2], LodDirection.EAST, maxX, y, z, zSize, ySize,
|
||||
color, skyLightTop, blockLight);
|
||||
}
|
||||
|
||||
private static void makeAdjQuads(LodQuadBuilder builder, long[] adjData, LodDirection direction, short x, short y,
|
||||
short z, short w0, short wy, int color, byte upSkyLight, byte blockLight) {
|
||||
color = ColorUtil.applyShade(color, MC.getShade(direction));
|
||||
long[] dataPoint = adjData;
|
||||
if (dataPoint == null || DataPointUtil.isVoid(dataPoint[0])) {
|
||||
builder.addQuadAdj(direction, x, y, z, w0, wy, color, (byte) 15, blockLight);
|
||||
return;
|
||||
}
|
||||
|
||||
int i;
|
||||
boolean firstFace = true;
|
||||
boolean allAbove = true;
|
||||
short nextStartingHeight = -1;
|
||||
byte nextSkyLight = upSkyLight;
|
||||
|
||||
// TODO transparency ocean floor fix
|
||||
// boolean isOpaque = ((colorMap[0] >> 24) & 0xFF) == 255;
|
||||
for (i = 0; i < dataPoint.length && DataPointUtil.doesItExist(adjData[i])
|
||||
&& !DataPointUtil.isVoid(adjData[i]); i++) {
|
||||
long adjPoint = adjData[i];
|
||||
|
||||
// TODO transparency ocean floor fix
|
||||
// if (isOpaque && DataPointUtil.getAlpha(singleAdjDataPoint) != 255)
|
||||
// continue;
|
||||
|
||||
short height = DataPointUtil.getHeight(adjPoint);
|
||||
short depth = DataPointUtil.getDepth(adjPoint);
|
||||
|
||||
// If the depth of said block is higher then our max Y, continue
|
||||
// Basically: y < maxY <= _____ height
|
||||
// _______&&: y < maxY <= depth
|
||||
if (y + wy <= depth)
|
||||
continue;
|
||||
// Now: depth < maxY
|
||||
allAbove = false;
|
||||
|
||||
if (height < y) {
|
||||
// Basically: _____ height < y < maxY
|
||||
// _______&&: depth ______ < y < maxY
|
||||
if (firstFace) {
|
||||
builder.addQuadAdj(direction, x, y, z, w0, wy, color, DataPointUtil.getLightSky(adjPoint),
|
||||
blockLight);
|
||||
} else {
|
||||
// Now: depth < height < y < previousDepth < maxY
|
||||
if (nextStartingHeight == -1)
|
||||
throw new RuntimeException("Loop error");
|
||||
builder.addQuadAdj(direction, x, y, z, w0, (short) (nextStartingHeight - y), color,
|
||||
DataPointUtil.getLightSky(adjPoint), blockLight);
|
||||
nextStartingHeight = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (depth <= y) { // AND y <= height
|
||||
if (y + wy <= height) {
|
||||
// Basically: ________ y < maxY <= height
|
||||
// _______&&: depth <= y < maxY
|
||||
// The face is inside adj face completely. Don't draw.
|
||||
break;
|
||||
}
|
||||
// Otherwise: ________ y <= Height < maxY
|
||||
// _______&&: depth <= y _________ < maxY
|
||||
// the adj data intersects the lower part of the current data
|
||||
// if this is the only face, use the maxY and break,
|
||||
// if there was another face we finish the last one and break
|
||||
if (firstFace) {
|
||||
builder.addQuadAdj(direction, x, height, z, w0, (short) (y + wy - height), color,
|
||||
DataPointUtil.getLightSky(adjPoint), blockLight);
|
||||
} else {
|
||||
// Now: depth <= y <= height < previousDepth < maxY
|
||||
if (nextStartingHeight == -1)
|
||||
throw new RuntimeException("Loop error");
|
||||
builder.addQuadAdj(direction, x, height, z, w0, (short) (nextStartingHeight - height), color,
|
||||
DataPointUtil.getLightSky(adjPoint), blockLight);
|
||||
nextStartingHeight = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// In here always true: y < depth < maxY
|
||||
// _________________&&: y < _____ (height and maxY)
|
||||
|
||||
if (y + wy <= height) {
|
||||
// Basically: y _______ < maxY <= height
|
||||
// _______&&: y < depth < maxY
|
||||
// the adj data intersects the higher part of the current data
|
||||
// we start the creation of a new face
|
||||
} else {
|
||||
// Otherwise: y < _____ height < maxY
|
||||
// _______&&: y < depth ______ < maxY
|
||||
if (firstFace) {
|
||||
builder.addQuadAdj(direction, x, height, z, w0, (short) (y + wy - height), color,
|
||||
DataPointUtil.getLightSky(adjPoint), blockLight);
|
||||
} else {
|
||||
// Now: y < depth < height < previousDepth < maxY
|
||||
if (nextStartingHeight == -1)
|
||||
throw new RuntimeException("Loop error");
|
||||
builder.addQuadAdj(direction, x, height, z, w0, (short) (nextStartingHeight - height), color,
|
||||
DataPointUtil.getLightSky(adjPoint), blockLight);
|
||||
nextStartingHeight = -1;
|
||||
}
|
||||
}
|
||||
// set next top as current depth
|
||||
nextStartingHeight = depth;
|
||||
firstFace = false;
|
||||
nextSkyLight = upSkyLight;
|
||||
if (i + 1 < adjData.length && DataPointUtil.doesItExist(adjData[i + 1]))
|
||||
nextSkyLight = DataPointUtil.getLightSky(adjData[i + 1]);
|
||||
}
|
||||
|
||||
if (allAbove) {
|
||||
builder.addQuadAdj(direction, x, y, z, w0, wy, color, upSkyLight, blockLight);
|
||||
} else if (nextStartingHeight != -1) {
|
||||
// We need to finish the last quad.
|
||||
builder.addQuadAdj(direction, x, y, z, w0, (short) (nextStartingHeight - y), color, nextSkyLight,
|
||||
blockLight);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,320 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Distant Horizon mod (formerly the LOD Mod),
|
||||
* licensed under the GNU GPL v3 License.
|
||||
*
|
||||
* Copyright (C) 2020 James Seibel
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU 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 General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package com.seibel.lod.core.objects.opengl;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
* A (almost) exact copy of Minecraft's
|
||||
* BufferBuilder object. <br>
|
||||
* Which allows for creating and filling
|
||||
* OpenGL buffers.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 12-9-2021
|
||||
*/
|
||||
public class LodBufferBuilder
|
||||
{
|
||||
public ByteBuffer buffer;
|
||||
|
||||
private int nextElementByte = 0;
|
||||
private int vertices;
|
||||
private LodVertexFormatElement currentElement;
|
||||
private int elementIndex;
|
||||
private LodVertexFormat format;
|
||||
private boolean building;
|
||||
|
||||
public LodBufferBuilder(int bufferSizeInBytes)
|
||||
{
|
||||
this.buffer = allocateByteBuffer(bufferSizeInBytes);
|
||||
}
|
||||
|
||||
public int getMemUsage() {return buffer.capacity();}
|
||||
|
||||
/** originally from MC's GLAllocation class */
|
||||
private ByteBuffer allocateByteBuffer(int bufferSizeInBytes)
|
||||
{
|
||||
return ByteBuffer.allocateDirect(bufferSizeInBytes).order(ByteOrder.nativeOrder());
|
||||
}
|
||||
|
||||
|
||||
/** make sure the buffer doesn't overflow when inserting new elements */
|
||||
private void ensureVertexCapacity()
|
||||
{
|
||||
this.ensureCapacity(this.format.getByteSize());
|
||||
}
|
||||
private void ensureCapacity(int vertexSizeInBytes)
|
||||
{
|
||||
if (this.nextElementByte + vertexSizeInBytes > this.buffer.capacity())
|
||||
{
|
||||
int i = this.buffer.capacity();
|
||||
int j = roundUp((int) ((i + vertexSizeInBytes)*2));
|
||||
//LOGGER.debug("Needed to grow BufferBuilder buffer: Old size {} bytes, new size {} bytes.", i, j);
|
||||
ByteBuffer bytebuffer = allocateByteBuffer(j);
|
||||
this.buffer.position(0);
|
||||
bytebuffer.put(this.buffer);
|
||||
bytebuffer.rewind();
|
||||
this.buffer = bytebuffer;
|
||||
}
|
||||
}
|
||||
private void packBuffer() {
|
||||
int cap = this.buffer.capacity();
|
||||
int filled = this.format.getByteSize() * this.vertices;
|
||||
this.buffer.position(0);
|
||||
this.buffer.limit(filled);
|
||||
if (cap - filled > 4096) {
|
||||
ByteBuffer bytebuffer = allocateByteBuffer(filled);
|
||||
bytebuffer.put(this.buffer);
|
||||
bytebuffer.rewind();
|
||||
this.buffer = bytebuffer;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static int roundUp(int vertexSizeInBytes)
|
||||
{
|
||||
int i = 4096; // 4 KB (1 page)
|
||||
if (vertexSizeInBytes == 0)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (vertexSizeInBytes < 0)
|
||||
{
|
||||
i *= -1;
|
||||
}
|
||||
|
||||
int j = vertexSizeInBytes % i;
|
||||
return j == 0 ? vertexSizeInBytes : vertexSizeInBytes + i - j;
|
||||
}
|
||||
}
|
||||
|
||||
private void switchFormat(LodVertexFormat newFormat)
|
||||
{
|
||||
format = newFormat;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
//========================================//
|
||||
// methods for actually building a buffer //
|
||||
//========================================//
|
||||
|
||||
/**
|
||||
* @param openGlLodVertexFormat GL11.GL_QUADS, GL11.GL_TRIANGLES, etc.
|
||||
* @param LodVertexFormat
|
||||
*/
|
||||
public void begin(int openGlLodVertexFormat, LodVertexFormat LodVertexFormat)
|
||||
{
|
||||
if (this.building)
|
||||
{
|
||||
throw new IllegalStateException("Already building!");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.building = true;
|
||||
this.switchFormat(LodVertexFormat);
|
||||
this.currentElement = LodVertexFormat.getElements().get(0);
|
||||
this.elementIndex = 0;
|
||||
this.buffer.clear();
|
||||
this.vertices = 0;
|
||||
}
|
||||
}
|
||||
|
||||
public void end()
|
||||
{
|
||||
if (!this.building)
|
||||
{
|
||||
return;
|
||||
} else {
|
||||
this.building = false;
|
||||
this.currentElement = null;
|
||||
this.elementIndex = 0;
|
||||
packBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
public void putByte(int index, byte newByte)
|
||||
{
|
||||
this.buffer.put(this.nextElementByte + index, newByte);
|
||||
}
|
||||
|
||||
public void putShort(int index, short newShort)
|
||||
{
|
||||
this.buffer.putShort(this.nextElementByte + index, newShort);
|
||||
}
|
||||
|
||||
public void putFloat(int index, float newFloat)
|
||||
{
|
||||
this.buffer.putFloat(this.nextElementByte + index, newFloat);
|
||||
}
|
||||
|
||||
public void endVertex()
|
||||
{
|
||||
if (this.elementIndex != 0)
|
||||
{
|
||||
throw new IllegalStateException("Not filled all elements of the vertex");
|
||||
}
|
||||
else
|
||||
{
|
||||
++this.vertices;
|
||||
this.ensureVertexCapacity();
|
||||
}
|
||||
}
|
||||
|
||||
public void nextElement()
|
||||
{
|
||||
ImmutableList<LodVertexFormatElement> immutablelist = this.format.getElements();
|
||||
this.elementIndex = (this.elementIndex + 1) % immutablelist.size();
|
||||
this.nextElementByte += this.currentElement.getByteSize();
|
||||
this.currentElement = immutablelist.get(this.elementIndex);
|
||||
if (currentElement.getIsPadding())
|
||||
{
|
||||
this.nextElement();
|
||||
}
|
||||
|
||||
// if (this.defaultColorSet && this.currentElement.getUsage() == LodVertexFormatElement.Usage.COLOR)
|
||||
// {
|
||||
// color(this.defaultR, this.defaultG, this.defaultB, this.defaultA);
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
public LodBufferBuilder color(int red, int green, int blue, int alpha)
|
||||
{
|
||||
LodVertexFormatElement LodVertexFormatelement = this.currentElement();
|
||||
if (LodVertexFormatelement.getType() != LodVertexFormatElement.DataType.UBYTE)
|
||||
{
|
||||
throw new IllegalStateException("Color must be stored as a UBYTE");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.putByte(0, (byte) red);
|
||||
this.putByte(1, (byte) green);
|
||||
this.putByte(2, (byte) blue);
|
||||
this.putByte(3, (byte) alpha);
|
||||
this.nextElement();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public LodBufferBuilder minecraftLightValue(byte lightValue)
|
||||
{
|
||||
LodVertexFormatElement LodVertexFormatelement = this.currentElement();
|
||||
if (LodVertexFormatelement.getType() != LodVertexFormatElement.DataType.UBYTE)
|
||||
{
|
||||
throw new IllegalStateException("Light Color must be stored as a UBYTE");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.putByte(0, lightValue);
|
||||
this.nextElement();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public LodBufferBuilder position(float x, float y, float z)
|
||||
{
|
||||
if (this.currentElement().getType() != LodVertexFormatElement.DataType.FLOAT)
|
||||
{
|
||||
throw new IllegalStateException("Position verticies must be stored as a FLOAT");
|
||||
}
|
||||
else
|
||||
{
|
||||
this.putFloat(0, x);
|
||||
this.putFloat(4, y);
|
||||
this.putFloat(8, z);
|
||||
this.nextElement();
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
public ByteBuffer getCleanedByteBuffer()
|
||||
{
|
||||
return this.buffer;
|
||||
}
|
||||
|
||||
public void reset()
|
||||
{
|
||||
this.nextElementByte = 0;
|
||||
this.vertices = 0;
|
||||
this.buffer.clear();
|
||||
}
|
||||
|
||||
public LodVertexFormatElement currentElement()
|
||||
{
|
||||
if (this.currentElement == null)
|
||||
{
|
||||
throw new IllegalStateException("BufferBuilder not started");
|
||||
}
|
||||
else
|
||||
{
|
||||
return this.currentElement;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean building()
|
||||
{
|
||||
return this.building;
|
||||
}
|
||||
|
||||
//==================//
|
||||
// internal classes //
|
||||
//==================//
|
||||
|
||||
public static final class DrawState
|
||||
{
|
||||
private final LodVertexFormat format;
|
||||
private final int vertexCount;
|
||||
private final int mode;
|
||||
|
||||
private DrawState(LodVertexFormat p_i225905_1_, int p_i225905_2_, int p_i225905_3_)
|
||||
{
|
||||
this.format = p_i225905_1_;
|
||||
this.vertexCount = p_i225905_2_;
|
||||
this.mode = p_i225905_3_;
|
||||
}
|
||||
|
||||
public LodVertexFormat format()
|
||||
{
|
||||
return this.format;
|
||||
}
|
||||
|
||||
public int vertexCount()
|
||||
{
|
||||
return this.vertexCount;
|
||||
}
|
||||
|
||||
public int mode()
|
||||
{
|
||||
return this.mode;
|
||||
}
|
||||
}
|
||||
|
||||
public LodVertexFormat getLodVertexFormat()
|
||||
{
|
||||
return this.format;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,228 @@
|
||||
package com.seibel.lod.core.objects.opengl;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
|
||||
import com.seibel.lod.core.enums.LodDirection;
|
||||
import com.seibel.lod.core.enums.LodDirection.Axis;
|
||||
import com.seibel.lod.core.util.ColorUtil;
|
||||
|
||||
public class LodQuadBuilder {
|
||||
static final int MAX_BUFFER_SIZE = (1024 * 1024 * 1);
|
||||
static final int QUAD_BYTE_SIZE = (12 * 6);
|
||||
static final int MAX_QUADS_PER_BUFFER = MAX_BUFFER_SIZE / QUAD_BYTE_SIZE;
|
||||
|
||||
static class Quad {
|
||||
final short x;
|
||||
final short y;
|
||||
final short z;
|
||||
final short w0;
|
||||
final short w1;
|
||||
final int color;
|
||||
final byte skylight;
|
||||
final byte blocklight;
|
||||
final LodDirection dir;
|
||||
|
||||
Quad(short x, short y, short z, short w0, short w1, int color, byte skylight, byte blocklight,
|
||||
LodDirection dir) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.w0 = w0;
|
||||
this.w1 = w1;
|
||||
this.color = color;
|
||||
this.skylight = skylight;
|
||||
this.blocklight = blocklight;
|
||||
this.dir = dir;
|
||||
}
|
||||
}
|
||||
|
||||
final ArrayList<Quad> quads;
|
||||
|
||||
public LodQuadBuilder(int initialSize) {
|
||||
quads = new ArrayList<Quad>(initialSize);
|
||||
}
|
||||
|
||||
public void addQuadAdj(LodDirection dir, short x, short y, short z, short w0, short wy, int color, byte skylight,
|
||||
byte blocklight) {
|
||||
if (dir.ordinal() <= LodDirection.DOWN.ordinal())
|
||||
throw new IllegalArgumentException("addQuadAdj() is only for adj direction! Not UP or Down!");
|
||||
quads.add(new Quad(x, y, z, w0, wy, color, skylight, blocklight, dir));
|
||||
}
|
||||
|
||||
// XZ
|
||||
public void addQuadUp(short x, short y, short z, short wx, short wz, int color, byte skylight, byte blocklight) {
|
||||
quads.add(new Quad(x, y, z, wx, wz, color, skylight, blocklight, LodDirection.UP));
|
||||
}
|
||||
|
||||
public void addQuadDown(short x, short y, short z, short wx, short wz, int color, byte skylight, byte blocklight) {
|
||||
quads.add(new Quad(x, y, z, wx, wz, color, skylight, blocklight, LodDirection.DOWN));
|
||||
}
|
||||
|
||||
// XY
|
||||
public void addQuadN(short x, short y, short z, short wx, short wy, int color, byte skylight, byte blocklight) {
|
||||
quads.add(new Quad(x, y, z, wx, wy, color, skylight, blocklight, LodDirection.NORTH));
|
||||
}
|
||||
|
||||
public void addQuadS(short x, short y, short z, short wx, short wy, int color, byte skylight, byte blocklight) {
|
||||
quads.add(new Quad(x, y, z, wx, wy, color, skylight, blocklight, LodDirection.SOUTH));
|
||||
}
|
||||
|
||||
// ZY
|
||||
public void addQuadW(short x, short y, short z, short wz, short wy, int color, byte skylight, byte blocklight) {
|
||||
quads.add(new Quad(x, y, z, wz, wy, color, skylight, blocklight, LodDirection.WEST));
|
||||
}
|
||||
|
||||
public void addQuadE(short x, short y, short z, short wz, short wy, int color, byte skylight, byte blocklight) {
|
||||
quads.add(new Quad(x, y, z, wz, wy, color, skylight, blocklight, LodDirection.EAST));
|
||||
}
|
||||
|
||||
private static void putVertex(ByteBuffer bb, short x, short y, short z, int color, byte skylight, byte blocklight) {
|
||||
skylight %= 16;
|
||||
blocklight %= 16;
|
||||
|
||||
bb.putShort(x);
|
||||
bb.putShort(y);
|
||||
bb.putShort(z);
|
||||
bb.putShort((short) (skylight | (blocklight << 4)));
|
||||
byte r = (byte) ColorUtil.getRed(color);
|
||||
byte g = (byte) ColorUtil.getGreen(color);
|
||||
byte b = (byte) ColorUtil.getBlue(color);
|
||||
byte a = (byte) ColorUtil.getAlpha(color);
|
||||
bb.put(r);
|
||||
bb.put(g);
|
||||
bb.put(b);
|
||||
bb.put(a);
|
||||
}
|
||||
|
||||
private static void putQuad(ByteBuffer bb, Quad quad) {
|
||||
int[][] quadBase = DIRECTION_VERTEX_QUAD[quad.dir.ordinal()];
|
||||
short d0 = quad.w0;
|
||||
short d1 = quad.w1;
|
||||
Axis axis = quad.dir.getAxis();
|
||||
for (int i = 0; i < quadBase.length; i++) {
|
||||
short dx, dy, dz;
|
||||
switch (axis) {
|
||||
case X: // ZY
|
||||
dx = 0;
|
||||
dz = quadBase[i][0] == 1 ? d0 : 0;
|
||||
dy = quadBase[i][1] == 1 ? d1 : 0;
|
||||
break;
|
||||
case Y: // XZ
|
||||
dy = 0;
|
||||
dx = quadBase[i][0] == 1 ? d0 : 0;
|
||||
dz = quadBase[i][1] == 1 ? d1 : 0;
|
||||
break;
|
||||
case Z: // XY
|
||||
dz = 0;
|
||||
dx = quadBase[i][0] == 1 ? d0 : 0;
|
||||
dy = quadBase[i][1] == 1 ? d1 : 0;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid Axis enum: " + axis);
|
||||
}
|
||||
putVertex(bb, (short) (quad.x + dx), (short) (quad.y + dy), (short) (quad.z + dz), quad.color,
|
||||
quad.skylight, quad.blocklight);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private ByteBuffer writeVertexData(ByteBuffer bb, int quadsStart, int quadsCount) {
|
||||
if (quadsStart + quadsCount > quads.size())
|
||||
quadsCount = quads.size() - quadsStart;
|
||||
bb.clear();
|
||||
bb.limit(quadsCount * QUAD_BYTE_SIZE);
|
||||
for (Quad quad : quads.subList(quadsStart, quadsStart + quadsCount)) {
|
||||
putQuad(bb, quad);
|
||||
}
|
||||
if (bb.hasRemaining())
|
||||
throw new RuntimeException();
|
||||
bb.rewind();
|
||||
return bb;
|
||||
}
|
||||
|
||||
public Iterator<ByteBuffer> makeVertexBuffers() {
|
||||
int numOfBuffers = getCurrentNeededVertexBuffers();
|
||||
return new Iterator<ByteBuffer>() {
|
||||
int counter = 0;
|
||||
ByteBuffer bb = ByteBuffer.allocateDirect(MAX_QUADS_PER_BUFFER * QUAD_BYTE_SIZE)
|
||||
.order(ByteOrder.nativeOrder());
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return counter < numOfBuffers;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ByteBuffer next() {
|
||||
if (counter >= numOfBuffers) {
|
||||
return null;
|
||||
}
|
||||
return writeVertexData(bb, MAX_QUADS_PER_BUFFER * counter++, MAX_QUADS_PER_BUFFER);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public int getCurrentNeededVertexBuffers() {
|
||||
return quads.size() / MAX_QUADS_PER_BUFFER + 1;
|
||||
}
|
||||
|
||||
public static final int[][][] DIRECTION_VERTEX_QUAD = new int[][][] {
|
||||
// X,Z
|
||||
{ // UP
|
||||
{ 1, 0 }, // 0
|
||||
{ 1, 1 }, // 1
|
||||
{ 0, 1 }, // 2
|
||||
|
||||
{ 1, 0 }, // 0
|
||||
{ 0, 1 }, // 2
|
||||
{ 0, 0 }, // 3
|
||||
}, { // DOWN
|
||||
{ 0, 0 }, // 0
|
||||
{ 0, 1 }, // 1
|
||||
{ 1, 1 }, // 2
|
||||
|
||||
{ 0, 0 }, // 0
|
||||
{ 1, 1 }, // 2
|
||||
{ 1, 0 }, // 3
|
||||
},
|
||||
// X,Y
|
||||
{ // NORTH
|
||||
{ 0, 0 }, // 0
|
||||
{ 0, 1 }, // 1
|
||||
{ 1, 1 }, // 2
|
||||
|
||||
{ 0, 0 }, // 0
|
||||
{ 1, 1 }, // 2
|
||||
{ 1, 0 }, // 3
|
||||
}, { // SOUTH
|
||||
{ 1, 0 }, // 0
|
||||
{ 1, 1 }, // 1
|
||||
{ 0, 1 }, // 2
|
||||
|
||||
{ 1, 0 }, // 0
|
||||
{ 0, 1 }, // 2
|
||||
{ 0, 0 }, // 3
|
||||
},
|
||||
// Z,Y
|
||||
{ // WEST
|
||||
{ 0, 0 }, // 0
|
||||
{ 1, 0 }, // 1
|
||||
{ 1, 1 }, // 2
|
||||
|
||||
{ 0, 0 }, // 0
|
||||
{ 1, 1 }, // 2
|
||||
{ 0, 1 }, // 3
|
||||
}, { // EAST
|
||||
{ 0, 1 }, // 0
|
||||
{ 1, 1 }, // 1
|
||||
{ 1, 0 }, // 2
|
||||
|
||||
{ 0, 1 }, // 0
|
||||
{ 1, 0 }, // 2
|
||||
{ 0, 0 }, // 3
|
||||
}, };
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package com.seibel.lod.core.objects.opengl;
|
||||
|
||||
public class RenderRegion implements AutoCloseable {
|
||||
LodVertexBuffer[] vbos;
|
||||
|
||||
public RenderRegion(int size) {
|
||||
vbos = new LodVertexBuffer[size];
|
||||
}
|
||||
|
||||
public void resize(int size) {
|
||||
if (vbos.length != size) {
|
||||
LodVertexBuffer[] newVbos = new LodVertexBuffer[size];
|
||||
if (vbos.length > size) {
|
||||
for (int i=size; i<vbos.length; i++) {
|
||||
vbos[i].close();
|
||||
vbos[i] = null;
|
||||
}
|
||||
}
|
||||
for (int i=0; i<newVbos.length && i<vbos.length; i++) {
|
||||
newVbos[i] = vbos[i];
|
||||
vbos[i] = null;
|
||||
}
|
||||
for (LodVertexBuffer b : vbos) {
|
||||
if (b != null) throw new RuntimeException("LEAKING VBO!");
|
||||
}
|
||||
vbos = newVbos;
|
||||
}
|
||||
}
|
||||
|
||||
public LodVertexBuffer[] debugGetBuffers() {
|
||||
return vbos;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
|
||||
|
||||
}
|
||||
|
||||
public LodVertexBuffer getOrMakeVbo(int iIndex, boolean useBuffStorage) {
|
||||
if (vbos[iIndex] == null) {
|
||||
vbos[iIndex] = new LodVertexBuffer(useBuffStorage);
|
||||
} else if (vbos[iIndex].isBufferStorage != useBuffStorage) {
|
||||
vbos[iIndex].close();
|
||||
vbos[iIndex] = new LodVertexBuffer(useBuffStorage);
|
||||
}
|
||||
return vbos[iIndex];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -24,7 +24,6 @@ import java.awt.Color;
|
||||
import com.seibel.lod.core.enums.rendering.FogDistance;
|
||||
import com.seibel.lod.core.enums.rendering.FogDrawMode;
|
||||
import com.seibel.lod.core.objects.math.Mat4f;
|
||||
import com.seibel.lod.core.objects.math.Vec3f;
|
||||
import com.seibel.lod.core.render.objects.ShaderProgram;
|
||||
import com.seibel.lod.core.render.objects.VertexAttribute;
|
||||
import com.seibel.lod.core.render.objects.VertexAttributePostGL43;
|
||||
@@ -40,11 +39,11 @@ public class LodRenderProgram extends ShaderProgram {
|
||||
// Attributes
|
||||
public final int posAttrib;
|
||||
public final int colAttrib;
|
||||
public final int lightAttrib; //Sky light then block light
|
||||
//public final int lightAttrib; //Sky light then block light
|
||||
// Uniforms
|
||||
public final int mvmUniform;
|
||||
public final int projUniform;
|
||||
public final int cameraUniform;
|
||||
//public final int cameraUniform;
|
||||
public final int fogColorUniform;
|
||||
// public final int skyLightUniform; worldSkyLight is currently not used
|
||||
public final int lightMapUniform;
|
||||
@@ -63,11 +62,11 @@ public class LodRenderProgram extends ShaderProgram {
|
||||
|
||||
posAttrib = getAttributeLocation("vPosition");
|
||||
colAttrib = getAttributeLocation("color");
|
||||
lightAttrib = getAttributeLocation("light");
|
||||
//lightAttrib = getAttributeLocation("light");
|
||||
|
||||
mvmUniform = getUniformLocation("modelViewMatrix");
|
||||
projUniform = getUniformLocation("projectionMatrix");
|
||||
cameraUniform = getUniformLocation("cameraPos");
|
||||
//cameraUniform = getUniformLocation("cameraPos");
|
||||
fogColorUniform = getUniformLocation("fogColor");
|
||||
// skyLightUniform = getUniformLocation("worldSkyLight");
|
||||
lightMapUniform = getUniformLocation("lightMap");
|
||||
@@ -90,9 +89,11 @@ public class LodRenderProgram extends ShaderProgram {
|
||||
else
|
||||
vao = new VertexAttributePreGL43(); // also binds VertexAttribute
|
||||
//vao.bind();
|
||||
vao.setVertexAttribute(0, posAttrib, VertexAttribute.VertexPointer.addVec3Pointer(false)); // 4+4+4
|
||||
// Now a pos+light.
|
||||
vao.setVertexAttribute(0, posAttrib, VertexAttribute.VertexPointer.addUnsignedShortsPointer(4, false)); // 2+2+2+2
|
||||
//vao.setVertexAttribute(0, posAttrib, VertexAttribute.VertexPointer.addVec3Pointer(false)); // 4+4+4
|
||||
vao.setVertexAttribute(0, colAttrib, VertexAttribute.VertexPointer.addUnsignedBytesPointer(4, true)); // +4
|
||||
vao.setVertexAttribute(0, lightAttrib, VertexAttribute.VertexPointer.addUnsignedBytesPointer(2, false)); // +4 due to how it aligns
|
||||
//vao.setVertexAttribute(0, lightAttrib, VertexAttribute.VertexPointer.addUnsignedBytesPointer(2, false)); // +4 due to how it aligns
|
||||
try {
|
||||
vao.completeAndCheck(vertexByteCount);
|
||||
} catch (RuntimeException e) {
|
||||
@@ -126,17 +127,20 @@ public class LodRenderProgram extends ShaderProgram {
|
||||
vao.unbindBuffersFromAllBindingPoint();
|
||||
}
|
||||
|
||||
public void fillUniformData(Mat4f modelViewMatrix, Mat4f projectionMatrix, Vec3f cameraPos, Color fogColor, int skyLight, int lightmapBindPoint) {
|
||||
public void fillUniformData(Mat4f projectionMatrix, Color fogColor, int skyLight, int lightmapBindPoint) {
|
||||
super.bind();
|
||||
// uniforms
|
||||
setUniform(mvmUniform, modelViewMatrix);
|
||||
setUniform(projUniform, projectionMatrix);
|
||||
setUniform(cameraUniform, cameraPos);
|
||||
setUniform(fogColorUniform, fogColor);
|
||||
// setUniform(skyLightUniform, skyLight);
|
||||
setUniform(lightMapUniform, lightmapBindPoint);
|
||||
}
|
||||
|
||||
public void fillUniformModelMatrix(Mat4f modelViewMatrix) {
|
||||
super.bind();
|
||||
setUniform(mvmUniform, modelViewMatrix);
|
||||
}
|
||||
|
||||
public void fillUniformDataForFog(LodFogConfig fogSettings, boolean allFogMode) {
|
||||
super.bind();
|
||||
if (allFogMode) {
|
||||
|
||||
@@ -29,6 +29,7 @@ import org.lwjgl.opengl.GL32;
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
import com.seibel.lod.core.api.ClientApi;
|
||||
import com.seibel.lod.core.builders.bufferBuilding.LodBufferBuilderFactory;
|
||||
import com.seibel.lod.core.builders.lodBuilding.LodBuilder;
|
||||
import com.seibel.lod.core.enums.rendering.DebugMode;
|
||||
import com.seibel.lod.core.enums.rendering.FogColorMode;
|
||||
import com.seibel.lod.core.enums.rendering.FogDistance;
|
||||
@@ -38,8 +39,10 @@ import com.seibel.lod.core.objects.math.Mat4f;
|
||||
import com.seibel.lod.core.objects.math.Vec3d;
|
||||
import com.seibel.lod.core.objects.math.Vec3f;
|
||||
import com.seibel.lod.core.objects.opengl.LodVertexBuffer;
|
||||
import com.seibel.lod.core.objects.opengl.RenderRegion;
|
||||
import com.seibel.lod.core.render.objects.LightmapTexture;
|
||||
import com.seibel.lod.core.util.DetailDistanceUtil;
|
||||
import com.seibel.lod.core.util.LevelPosUtil;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.util.MovableGridList;
|
||||
import com.seibel.lod.core.util.SingletonHandler;
|
||||
@@ -145,7 +148,7 @@ public class LodRenderer
|
||||
* @param mcProjectionMatrix
|
||||
* @param partialTicks how far into the current tick this method was called.
|
||||
*/
|
||||
public void drawLODs(LodDimension lodDim, Mat4f mcModelViewMatrix, Mat4f mcProjectionMatrix, float partialTicks, IProfilerWrapper profiler)
|
||||
public void drawLODs(LodDimension lodDim, Mat4f baseModelViewMatrix, Mat4f baseProjectionMatrix, float partialTicks, IProfilerWrapper profiler)
|
||||
{
|
||||
//=================================//
|
||||
// determine if LODs should render //
|
||||
@@ -216,11 +219,11 @@ public class LodRenderer
|
||||
}
|
||||
swapBuffer.end("SwapBuffer");
|
||||
// Get the front buffers to draw
|
||||
MovableGridList<LodVertexBuffer[]> vbos = lodBufferBuilderFactory.getFrontBuffers();
|
||||
MovableGridList<RenderRegion> regions = lodBufferBuilderFactory.getFrontBuffers();
|
||||
int vbosCenterX = lodBufferBuilderFactory.getFrontBuffersCenterX();
|
||||
int vbosCenterZ = lodBufferBuilderFactory.getFrontBuffersCenterZ();
|
||||
|
||||
if (vbos == null) {
|
||||
if (regions == null) {
|
||||
// There is no vbos, which means nothing needs to be drawn. So skip rendering
|
||||
return;
|
||||
}
|
||||
@@ -282,7 +285,6 @@ public class LodRenderer
|
||||
|
||||
/*---------Get required data--------*/
|
||||
// Get the matrixs for rendering
|
||||
Mat4f modelViewMatrix = translateModelViewMatrix(mcModelViewMatrix, partialTicks, vbosCenterX, vbosCenterZ);
|
||||
int vanillaBlockRenderedDistance = MC_RENDER.getRenderDistance() * LodUtil.CHUNK_WIDTH;
|
||||
int farPlaneBlockDistance;
|
||||
// required for setupFog and setupProjectionMatrix
|
||||
@@ -290,15 +292,16 @@ public class LodRenderer
|
||||
farPlaneBlockDistance = Math.min(CONFIG.client().graphics().quality().getLodChunkRenderDistance(), LodUtil.CEILED_DIMENSION_MAX_RENDER_DISTANCE) * LodUtil.CHUNK_WIDTH;
|
||||
else
|
||||
farPlaneBlockDistance = CONFIG.client().graphics().quality().getLodChunkRenderDistance() * LodUtil.CHUNK_WIDTH;
|
||||
Mat4f projectionMatrix = createProjectionMatrix(mcProjectionMatrix, vanillaBlockRenderedDistance, farPlaneBlockDistance);
|
||||
LodFogConfig fogSettings = new LodFogConfig(CONFIG, REFLECTION_HANDLER, farPlaneBlockDistance, vanillaBlockRenderedDistance);
|
||||
drawCalculateParams.end("drawCalculateParams");
|
||||
Mat4f projectionMatrix = createProjectionMatrix(baseProjectionMatrix, vanillaBlockRenderedDistance, farPlaneBlockDistance);
|
||||
|
||||
/*---------Fill uniform data--------*/
|
||||
LagSpikeCatcher drawFillData = new LagSpikeCatcher();
|
||||
// Fill the uniform data. Note: GL33.GL_TEXTURE0 == texture bindpoint 0
|
||||
shaderProgram.fillUniformData(modelViewMatrix, projectionMatrix, getTranslatedCameraPos(vbosCenterX, vbosCenterZ),
|
||||
MC_RENDER.isFogStateSpecial() ? getSpecialFogColor(partialTicks) : getFogColor(partialTicks), (int) (MC.getSkyDarken(partialTicks) * 15), 0);
|
||||
shaderProgram.fillUniformData(projectionMatrix,
|
||||
MC_RENDER.isFogStateSpecial() ? getSpecialFogColor(partialTicks) : getFogColor(partialTicks),
|
||||
(int) (MC.getSkyDarken(partialTicks) * 15), 0);
|
||||
// Previous guy said fog setting may be different from region to region, but the fogSettings never changed... soooooo...
|
||||
shaderProgram.fillUniformDataForFog(fogSettings, MC_RENDER.isFogStateSpecial());
|
||||
// Note: Since lightmapTexture is changing every frame, it's faster to recreate it than to reuse the old one.
|
||||
@@ -317,16 +320,28 @@ public class LodRenderer
|
||||
|
||||
// where the center of the buffers is (needed when culling regions)
|
||||
// render each of the buffers
|
||||
int lowRegionX = vbos.getCenterX() - vbos.gridCentreToEdge;
|
||||
int lowRegionZ = vbos.getCenterY() - vbos.gridCentreToEdge;
|
||||
int lowRegionX = regions.getCenterX() - regions.gridCentreToEdge;
|
||||
int lowRegionZ = regions.getCenterY() - regions.gridCentreToEdge;
|
||||
int drawCall = 0;
|
||||
int vCount0 = 0;
|
||||
for (int regionX=lowRegionX; regionX<lowRegionX+vbos.gridSize; regionX++) {
|
||||
for (int regionZ=lowRegionZ; regionZ<lowRegionZ+vbos.gridSize; regionZ++) {
|
||||
if (vbos.get(regionX, regionZ) == null) continue;
|
||||
for (int regionX=lowRegionX; regionX<lowRegionX+regions.gridSize; regionX++) {
|
||||
for (int regionZ=lowRegionZ; regionZ<lowRegionZ+regions.gridSize; regionZ++) {
|
||||
if (regions.get(regionX, regionZ) == null) continue;
|
||||
|
||||
if (cullingDisabled || RenderUtil.isRegionInViewFrustum(MC_RENDER.getCameraBlockPosition(),
|
||||
MC_RENDER.getLookAtVector(), regionX, regionZ)) {
|
||||
for (LodVertexBuffer vbo : vbos.get(regionX, regionZ)) {
|
||||
RenderRegion region = regions.get(regionX, regionZ);
|
||||
//TODO improve this
|
||||
Vec3d cameraPos = MC_RENDER.getCameraExactPosition();
|
||||
|
||||
Mat4f localModelViewMatrix = baseModelViewMatrix.copy();
|
||||
localModelViewMatrix.multiplyTranslationMatrix(
|
||||
(regionX * LodUtil.REGION_WIDTH) - cameraPos.x,
|
||||
LodBuilder.MIN_WORLD_HEIGHT - cameraPos.y,
|
||||
(regionZ * LodUtil.REGION_WIDTH) - cameraPos.z);
|
||||
shaderProgram.fillUniformModelMatrix(localModelViewMatrix);
|
||||
|
||||
for (LodVertexBuffer vbo : region.debugGetBuffers()) {
|
||||
if (vbo == null) continue;
|
||||
if (vbo.vertexCount == 0) {
|
||||
vCount0++;
|
||||
@@ -419,42 +434,6 @@ public class LodRenderer
|
||||
{
|
||||
return MC_RENDER.getSpecialFogColor(partialTicks);
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate the camera relative to the LodDimension's center,
|
||||
* this is done since all LOD buffers are created in world space
|
||||
* instead of object space.
|
||||
* (since AxisAlignedBoundingBoxes (LODs) use doubles and thus have a higher
|
||||
* accuracy vs the model view matrix, which only uses floats)
|
||||
*/
|
||||
private Mat4f translateModelViewMatrix(Mat4f mcModelViewMatrix, float partialTicks, int vbosCenterX, int vbosCenterZ)
|
||||
{
|
||||
// get all relevant camera info
|
||||
Vec3d projectedView = MC_RENDER.getCameraExactPosition();
|
||||
|
||||
// translate the camera relative to the regions' center
|
||||
// (AxisAlignedBoundingBoxes (LODs) use doubles and thus have a higher
|
||||
// accuracy vs the model view matrix, which only uses floats)
|
||||
//int bufferPosX = LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, vbosCenterX, LodUtil.BLOCK_DETAIL_LEVEL);
|
||||
//int bufferPosZ = LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, vbosCenterZ, LodUtil.BLOCK_DETAIL_LEVEL);
|
||||
double xDiff = projectedView.x - vbosCenterX;
|
||||
double zDiff = projectedView.z - vbosCenterZ;
|
||||
mcModelViewMatrix.multiplyTranslationMatrix(-xDiff, -projectedView.y, -zDiff);
|
||||
|
||||
return mcModelViewMatrix;
|
||||
}
|
||||
|
||||
/**
|
||||
* Similar to translateModelViewMatrix (above),
|
||||
* but for the camera position
|
||||
*/
|
||||
private Vec3f getTranslatedCameraPos(int vbosCenterX, int vbosCenterZ)
|
||||
{
|
||||
//int worldCenterX = LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, vbosCenterX, LodUtil.BLOCK_DETAIL_LEVEL);
|
||||
//int worldCenterZ = LevelPosUtil.convert(LodUtil.CHUNK_DETAIL_LEVEL, vbosCenterZ, LodUtil.BLOCK_DETAIL_LEVEL);
|
||||
Vec3d cameraPos = MC_RENDER.getCameraExactPosition();
|
||||
return new Vec3f((float)cameraPos.x - vbosCenterX, (float)cameraPos.y, (float)cameraPos.z - vbosCenterZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* create and return a new projection matrix based on MC's projection matrix
|
||||
|
||||
@@ -48,8 +48,8 @@ public class LightmapTexture {
|
||||
MC.sendChatMessage(same + " " + badIndex);
|
||||
*/
|
||||
// comment this line out to prevent uploading the new lightmap
|
||||
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_RGBA, lightMapWidth,
|
||||
lightMapHeight, 0, GL32.GL_RGBA, GL32.GL_UNSIGNED_BYTE, pixels);
|
||||
GL32.glTexImage2D(GL32.GL_TEXTURE_2D, 0, GL32.GL_RGBA, lightMapWidth*lightMapHeight,
|
||||
1, 0, GL32.GL_RGBA, GL32.GL_UNSIGNED_BYTE, pixels);
|
||||
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_WRAP_S, GL32.GL_CLAMP_TO_BORDER);
|
||||
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_WRAP_T, GL32.GL_CLAMP_TO_BORDER);
|
||||
GL32.glTexParameteri(GL32.GL_TEXTURE_2D, GL32.GL_TEXTURE_MIN_FILTER, GL32.GL_NEAREST);
|
||||
|
||||
@@ -34,6 +34,10 @@ public abstract class VertexAttribute {
|
||||
this.normalized = normalized;
|
||||
this.byteSize = byteSize;
|
||||
}
|
||||
private static int _align(int bytes) {
|
||||
return (-Math.floorDiv(-bytes, 4))*4;
|
||||
}
|
||||
|
||||
public static VertexPointer addFloatPointer(boolean normalized) {
|
||||
return new VertexPointer(1, GL32.GL_FLOAT, normalized, 4);
|
||||
}
|
||||
@@ -50,7 +54,10 @@ public abstract class VertexAttribute {
|
||||
return new VertexPointer(1, GL32.GL_UNSIGNED_BYTE, normalized, 4); // Always aligned to 4 bytes
|
||||
}
|
||||
public static VertexPointer addUnsignedBytesPointer(int elementCount, boolean normalized) {
|
||||
return new VertexPointer(elementCount, GL32.GL_UNSIGNED_BYTE, normalized, (-Math.floorDiv(-elementCount, 4))*4); // aligned to 4 bytes
|
||||
return new VertexPointer(elementCount, GL32.GL_UNSIGNED_BYTE, normalized, _align(elementCount)); // aligned to 4 bytes
|
||||
}
|
||||
public static VertexPointer addUnsignedShortsPointer(int elementCount, boolean normalized) {
|
||||
return new VertexPointer(elementCount, GL32.GL_UNSIGNED_SHORT, normalized, _align(elementCount*2));
|
||||
}
|
||||
public static VertexPointer addIntPointer(boolean normalized) {
|
||||
return new VertexPointer(1, GL32.GL_INT, normalized, 4);
|
||||
|
||||
@@ -27,7 +27,6 @@ import com.seibel.lod.core.enums.LodDirection;
|
||||
import com.seibel.lod.core.enums.config.HorizontalResolution;
|
||||
import com.seibel.lod.core.enums.config.VanillaOverdraw;
|
||||
import com.seibel.lod.core.handlers.IReflectionHandler;
|
||||
import com.seibel.lod.core.objects.VertexOptimizer;
|
||||
import com.seibel.lod.core.objects.lod.LodDimension;
|
||||
import com.seibel.lod.core.objects.lod.RegionPos;
|
||||
import com.seibel.lod.core.objects.opengl.DefaultLodVertexFormats;
|
||||
@@ -398,10 +397,10 @@ public class LodUtil
|
||||
return false;
|
||||
int tempX;
|
||||
int tempZ;
|
||||
for (LodDirection lodDirection : VertexOptimizer.ADJ_DIRECTIONS)
|
||||
for (LodDirection lodDirection : LodDirection.ADJ_DIRECTIONS)
|
||||
{
|
||||
tempX = x + VertexOptimizer.DIRECTION_NORMAL_MAP.get(lodDirection).x;
|
||||
tempZ = z + VertexOptimizer.DIRECTION_NORMAL_MAP.get(lodDirection).z;
|
||||
tempX = x + lodDirection.getNormal().x;
|
||||
tempZ = z + lodDirection.getNormal().z;
|
||||
if (vanillaRenderedChunks[x][z] || (!(tempX < 0 || tempZ < 0 || tempX >= vanillaRenderedChunks.length || tempZ >= vanillaRenderedChunks[0].length)
|
||||
&& !vanillaRenderedChunks[tempX][tempZ]))
|
||||
return true;
|
||||
@@ -410,7 +409,7 @@ public class LodUtil
|
||||
}
|
||||
public static boolean isBorderChunk(MovableGridList<Boolean> vanillaRenderedChunks, int chunkX, int chunkZ)
|
||||
{
|
||||
for (LodDirection lodDirection : VertexOptimizer.ADJ_DIRECTIONS)
|
||||
for (LodDirection lodDirection : LodDirection.ADJ_DIRECTIONS)
|
||||
{
|
||||
int tempX = chunkX + lodDirection.getNormal().x;
|
||||
int tempZ = chunkZ + lodDirection.getNormal().z;
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
#version 150 core
|
||||
|
||||
in vec4 vertexColor;
|
||||
in vec4 vertexWorldPos;
|
||||
|
||||
|
||||
in float dist;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
|
||||
uniform vec3 cameraPos;
|
||||
|
||||
uniform bool fogEnabled;
|
||||
uniform bool nearFogEnabled;
|
||||
uniform bool farFogEnabled;
|
||||
@@ -44,7 +39,6 @@ void main()
|
||||
{
|
||||
// add fog
|
||||
|
||||
float dist = distance(vertexWorldPos, vec4(cameraPos,1));
|
||||
// no fog by default
|
||||
float fogAlpha = 0;
|
||||
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
#version 150 core
|
||||
|
||||
in vec3 vPosition;
|
||||
in vec4 vPosition;
|
||||
in vec4 color;
|
||||
in vec2 light;
|
||||
|
||||
out vec4 vertexColor;
|
||||
out vec4 vertexWorldPos;
|
||||
out float depth;
|
||||
|
||||
out float dist;
|
||||
|
||||
uniform mat4 modelViewMatrix;
|
||||
uniform mat4 projectionMatrix;
|
||||
@@ -21,31 +18,18 @@ uniform sampler2D lightMap;
|
||||
*
|
||||
* author: James Seibel
|
||||
* version: 12-8-2021
|
||||
*
|
||||
* updated: TomTheFurry
|
||||
* version: 15-2-2022
|
||||
*/
|
||||
void main()
|
||||
{
|
||||
float blockSkyLight = light[0];
|
||||
float blockLight = light[1];
|
||||
vec4 worldSpacePos = modelViewMatrix * vec4(vPosition.xyz,1);
|
||||
float light = (vPosition.a+0.5) / 256.0;
|
||||
|
||||
// just skylight
|
||||
// good for sanity checks; but will cause OpenGL errors since we are binding unused data
|
||||
// vertexColor = vec4(color.xyz * worldSkyLight / 16.0, color.w);
|
||||
vertexColor = color * texture(lightMap, vec2(light,0.5));
|
||||
|
||||
float blockLightTex = blockLight / 16.0;
|
||||
float skyLightTex = blockSkyLight / 16.0;
|
||||
dist = length(worldSpacePos.xyz);
|
||||
|
||||
// we don't really need alpha in the lightmap
|
||||
// vertexColor = color * vec4(texture(lightMap, vec2(skyLightTex, blockLightTex)).xyz, 1);
|
||||
vertexColor = color * texture(lightMap, vec2(skyLightTex, blockLightTex));
|
||||
|
||||
|
||||
|
||||
// TODO: add a simple white texture to support Optifine shaders
|
||||
//textureCoord = textureCoord;
|
||||
|
||||
vertexWorldPos = vec4(vPosition, 1);
|
||||
|
||||
// the vPosition needs to be converted to a vec4 so it can be multiplied
|
||||
// by the 4x4 matrices
|
||||
gl_Position = projectionMatrix * modelViewMatrix * vec4(vPosition, 1);
|
||||
gl_Position = projectionMatrix * worldSpacePos;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user