Add variable detail LODs
This commit is contained in:
@@ -3,6 +3,9 @@ package com.seibel.lod.objects;
|
||||
import java.awt.Color;
|
||||
|
||||
import com.seibel.lod.enums.ColorDirection;
|
||||
import com.seibel.lod.enums.LodDetail;
|
||||
import com.seibel.lod.handlers.LodDimensionFileHandler;
|
||||
import com.seibel.lod.util.LodConfig;
|
||||
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
|
||||
@@ -11,7 +14,7 @@ import net.minecraft.util.math.ChunkPos;
|
||||
* and color data for an LOD object.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 05-29-2021
|
||||
* @version 6-12-2021
|
||||
*/
|
||||
public class LodChunk
|
||||
{
|
||||
@@ -19,39 +22,29 @@ public class LodChunk
|
||||
private static final int DATA_DELIMITER_COUNT = 22;
|
||||
|
||||
/** This is what separates each piece of data in the toData method */
|
||||
public static final char DATA_DELIMITER = ',';
|
||||
private static final char DATA_DELIMITER = LodDimensionFileHandler.DATA_DELIMITER;
|
||||
|
||||
/** Width of a Minecraft Chunk */
|
||||
public static final int WIDTH = 16;
|
||||
|
||||
/** alpha used when drawing chunks in debug mode */
|
||||
private static final int DEBUG_ALPHA = 255; // 0 - 255
|
||||
private static final Color DEBUG_BLACK = new Color(0, 0, 0, DEBUG_ALPHA);
|
||||
private static final Color DEBUG_WHITE = new Color(255, 255, 255, DEBUG_ALPHA);
|
||||
private static final Color INVISIBLE = new Color(0,0,0,0);
|
||||
|
||||
|
||||
public static final LodDetail DETAIL = LodDetail.QUAD;
|
||||
|
||||
|
||||
/** The x coordinate of the chunk. */
|
||||
public int x = 0;
|
||||
/** The z coordinate of the chunk. */
|
||||
public int z = 0;
|
||||
|
||||
/*
|
||||
* The reason we are only using 1 height and depth point
|
||||
* instead of multiple is because:
|
||||
* 1. more points would drastically increase the amount of
|
||||
* memory and disk space needed
|
||||
* 2. more height/depth points require more color points,
|
||||
* which can get out of hand quickly
|
||||
* 3. with the increased disk space reading/writing would
|
||||
* take far too long
|
||||
* 4. the increased resolution is generally not worth it,
|
||||
* 4 LODs per chunk is the limit of diminishing returns.
|
||||
* And some of that could potentially be faked through
|
||||
* smart LodTemplates
|
||||
*/
|
||||
private short height;
|
||||
private short depth;
|
||||
|
||||
/** The average color for the 6 cardinal directions */
|
||||
public Color colors[];
|
||||
/** This stores the height and color for each data point in the LodChunk */
|
||||
public LodDataPoint dataPoints[][];
|
||||
|
||||
/** If true then this LodChunk contains no data */
|
||||
private boolean empty = false;
|
||||
@@ -67,16 +60,11 @@ public class LodChunk
|
||||
x = 0;
|
||||
z = 0;
|
||||
|
||||
height = 0;
|
||||
depth = 0;
|
||||
colors = new Color[ColorDirection.values().length];
|
||||
|
||||
// by default have the colors invisible
|
||||
for(ColorDirection dir : ColorDirection.values())
|
||||
colors[dir.value] = INVISIBLE;
|
||||
dataPoints = new LodDataPoint[DETAIL.lengthCount][DETAIL.lengthCount];
|
||||
}
|
||||
|
||||
|
||||
// TODO
|
||||
/**
|
||||
* Creates an LodChunk from the string
|
||||
* generated by the toData method.
|
||||
@@ -84,107 +72,107 @@ public class LodChunk
|
||||
* @throws IllegalArgumentException if the data isn't valid to create a LodChunk
|
||||
* @throws NumberFormatException if any piece of data can't be converted at any point
|
||||
*/
|
||||
public LodChunk(String data) throws IllegalArgumentException, NumberFormatException
|
||||
{
|
||||
/*
|
||||
* data format:
|
||||
* x, z, height, depth, rgb color data
|
||||
*
|
||||
* example:
|
||||
* 5,8, 4, 0, 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
|
||||
*/
|
||||
|
||||
// make sure there are the correct number of entries
|
||||
// in the data string (28)
|
||||
int count = 0;
|
||||
|
||||
for(int i = 0; i < data.length(); i++)
|
||||
if(data.charAt(i) == DATA_DELIMITER)
|
||||
count++;
|
||||
|
||||
if(count != DATA_DELIMITER_COUNT)
|
||||
throw new IllegalArgumentException("LodChunk constructor givin an invalid string. The data given had " + count + " delimiters when it should have had " + DATA_DELIMITER_COUNT + ".");
|
||||
|
||||
|
||||
|
||||
// index we will use when going through the String
|
||||
int index = 0;
|
||||
int lastIndex = 0;
|
||||
|
||||
|
||||
|
||||
// x and z position
|
||||
index = data.indexOf(DATA_DELIMITER, 0);
|
||||
x = Integer.parseInt(data.substring(0,index));
|
||||
|
||||
lastIndex = index;
|
||||
index = data.indexOf(DATA_DELIMITER, lastIndex+1);
|
||||
z = Integer.parseInt(data.substring(lastIndex+1,index));
|
||||
|
||||
// height
|
||||
lastIndex = index;
|
||||
index = data.indexOf(DATA_DELIMITER, lastIndex+1);
|
||||
height = Short.parseShort(data.substring(lastIndex+1,index));
|
||||
|
||||
// depth
|
||||
lastIndex = index;
|
||||
index = data.indexOf(DATA_DELIMITER, lastIndex+1);
|
||||
depth = Short.parseShort(data.substring(lastIndex+1,index));
|
||||
|
||||
|
||||
|
||||
// color
|
||||
colors = new Color[6];
|
||||
for(ColorDirection dir : ColorDirection.values())
|
||||
{
|
||||
int red = 0;
|
||||
int green = 0;
|
||||
int blue = 0;
|
||||
|
||||
// get r,g,b
|
||||
for(int i = 0; i < 3; i++)
|
||||
{
|
||||
lastIndex = index;
|
||||
index = data.indexOf(DATA_DELIMITER, lastIndex + 1);
|
||||
|
||||
String raw = "";
|
||||
switch(i)
|
||||
{
|
||||
case 0:
|
||||
raw = data.substring(lastIndex+1,index);
|
||||
red = Short.parseShort(raw);
|
||||
break;
|
||||
case 1:
|
||||
raw = data.substring(lastIndex+1,index);
|
||||
green = Short.parseShort(raw);
|
||||
break;
|
||||
case 2:
|
||||
raw = data.substring(lastIndex+1,index);
|
||||
blue = Short.parseShort(raw);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
colors[dir.value] = new Color(red, green, blue);
|
||||
}
|
||||
|
||||
|
||||
// after going through all this
|
||||
// is this LOD empty?
|
||||
empty = determineIfEmtpy();
|
||||
}
|
||||
// public LodChunk(String data) throws IllegalArgumentException, NumberFormatException
|
||||
// {
|
||||
// /*
|
||||
// * data format:
|
||||
// * x, z, height, depth, rgb color data
|
||||
// *
|
||||
// * example:
|
||||
// * 5,8, 4, 0, 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
|
||||
// */
|
||||
//
|
||||
// // make sure there are the correct number of entries
|
||||
// // in the data string (28)
|
||||
// int count = 0;
|
||||
//
|
||||
// for(int i = 0; i < data.length(); i++)
|
||||
// if(data.charAt(i) == DATA_DELIMITER)
|
||||
// count++;
|
||||
//
|
||||
// if(count != DATA_DELIMITER_COUNT)
|
||||
// throw new IllegalArgumentException("LodChunk constructor givin an invalid string. The data given had " + count + " delimiters when it should have had " + DATA_DELIMITER_COUNT + ".");
|
||||
//
|
||||
//
|
||||
//
|
||||
// // index we will use when going through the String
|
||||
// int index = 0;
|
||||
// int lastIndex = 0;
|
||||
//
|
||||
//
|
||||
//
|
||||
// // x and z position
|
||||
// index = data.indexOf(DATA_DELIMITER, 0);
|
||||
// x = Integer.parseInt(data.substring(0,index));
|
||||
//
|
||||
// lastIndex = index;
|
||||
// index = data.indexOf(DATA_DELIMITER, lastIndex+1);
|
||||
// z = Integer.parseInt(data.substring(lastIndex+1,index));
|
||||
//
|
||||
// // height
|
||||
// lastIndex = index;
|
||||
// index = data.indexOf(DATA_DELIMITER, lastIndex+1);
|
||||
// // TODO
|
||||
// //height = Short.parseShort(data.substring(lastIndex+1,index));
|
||||
//
|
||||
// // depth
|
||||
// lastIndex = index;
|
||||
// index = data.indexOf(DATA_DELIMITER, lastIndex+1);
|
||||
// //depth = Short.parseShort(data.substring(lastIndex+1,index));
|
||||
//
|
||||
//
|
||||
//
|
||||
// // color
|
||||
// //colors = new Color[6];
|
||||
// for(ColorDirection dir : ColorDirection.values())
|
||||
// {
|
||||
// int red = 0;
|
||||
// int green = 0;
|
||||
// int blue = 0;
|
||||
//
|
||||
// // get r,g,b
|
||||
// for(int i = 0; i < 3; i++)
|
||||
// {
|
||||
// lastIndex = index;
|
||||
// index = data.indexOf(DATA_DELIMITER, lastIndex + 1);
|
||||
//
|
||||
// String raw = "";
|
||||
// switch(i)
|
||||
// {
|
||||
// case 0:
|
||||
// raw = data.substring(lastIndex+1,index);
|
||||
// red = Short.parseShort(raw);
|
||||
// break;
|
||||
// case 1:
|
||||
// raw = data.substring(lastIndex+1,index);
|
||||
// green = Short.parseShort(raw);
|
||||
// break;
|
||||
// case 2:
|
||||
// raw = data.substring(lastIndex+1,index);
|
||||
// blue = Short.parseShort(raw);
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // TODO
|
||||
// //colors[dir.value] = new Color(red, green, blue);
|
||||
// }
|
||||
//
|
||||
//
|
||||
// // after going through all this
|
||||
// // is this LOD empty?
|
||||
// empty = determineIfEmtpy();
|
||||
// }
|
||||
|
||||
/**
|
||||
* Create a LodChunk from the given values.
|
||||
*/
|
||||
public LodChunk(ChunkPos pos, short newHeight, short newDepth, Color[] newColors)
|
||||
public LodChunk(ChunkPos pos, LodDataPoint[][] newDataPoints)
|
||||
{
|
||||
x = pos.x;
|
||||
z = pos.z;
|
||||
|
||||
height = newHeight;
|
||||
depth = newDepth;
|
||||
colors = newColors;
|
||||
dataPoints = newDataPoints;
|
||||
|
||||
empty = determineIfEmtpy();
|
||||
}
|
||||
@@ -217,27 +205,30 @@ public class LodChunk
|
||||
*/
|
||||
private boolean determineIfEmtpy()
|
||||
{
|
||||
// we don't check the depth since the
|
||||
// height should always be greater than or equal
|
||||
// to the depth
|
||||
if(height >= 0)
|
||||
for(LodDataPoint[] dataPointArray : dataPoints)
|
||||
{
|
||||
// the height is valid,
|
||||
// do we have at least 1 non-invisible color?
|
||||
|
||||
for(ColorDirection dir : ColorDirection.values())
|
||||
if(!colors[dir.value].equals(INVISIBLE))
|
||||
// at least one direction has a non-invisible color
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// the height is negative,
|
||||
// this LodChunk is empty
|
||||
return true;
|
||||
for(LodDataPoint dataPoint : dataPointArray)
|
||||
{
|
||||
if (dataPoint == null)
|
||||
continue;
|
||||
|
||||
// we don't check the depth since the
|
||||
// height should always be greater than or equal
|
||||
// to the depth
|
||||
if(dataPoint.height >= 0)
|
||||
{
|
||||
// the height is valid,
|
||||
// do we have at least 1 non-invisible color?
|
||||
for(ColorDirection dir : ColorDirection.values())
|
||||
if(!dataPoint.colors[dir.value].equals(INVISIBLE))
|
||||
// at least one direction has a non-invisible color
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// we checked everywhere, this LodChunk is empty
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -247,28 +238,124 @@ public class LodChunk
|
||||
// output //
|
||||
//========//
|
||||
|
||||
/**
|
||||
* Returns the data point for the given relative block position.
|
||||
*/
|
||||
public LodDataPoint getDataPointForBlockPos(int blockX, int blockZ)
|
||||
{
|
||||
if (blockX < 0 || blockX > WIDTH || blockX < 0 || blockZ > WIDTH)
|
||||
throw new IllegalArgumentException("The coordinates given are outside the LodChunk");
|
||||
|
||||
return dataPoints[blockX / DETAIL.width][blockZ / DETAIL.width];
|
||||
}
|
||||
|
||||
/** Returns the color for the given direction */
|
||||
public Color getColor(ColorDirection dir)
|
||||
public Color getColorForBlockPos(int blockX, int blockZ, ColorDirection dir)
|
||||
{
|
||||
return colors[dir.value];
|
||||
return getDataPointForBlockPos(blockX, blockZ).colors[dir.value];
|
||||
}
|
||||
|
||||
public short getHeight()
|
||||
public short getHeightForBlockPos(int blockX, int blockZ)
|
||||
{
|
||||
return height;
|
||||
return getDataPointForBlockPos(blockX, blockZ).height;
|
||||
}
|
||||
|
||||
public short getDepth()
|
||||
public short getDepthForBlockPos(int blockX, int blockZ)
|
||||
{
|
||||
return depth;
|
||||
return getDataPointForBlockPos(blockX, blockZ).depth;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param startX
|
||||
* @param startZ
|
||||
* @param endX
|
||||
* @param endZ
|
||||
* @return
|
||||
*/
|
||||
public short getAverageHeightOverArea(int startX, int startZ, int endX, int endZ)
|
||||
{
|
||||
int average = 0;
|
||||
|
||||
for(int x = startX; x < endX; x++)
|
||||
for(int z = startZ; z < endZ; z++)
|
||||
average += getHeightForBlockPos(x,z);
|
||||
|
||||
return (short) (average / ((endX - startX) * (endZ - startZ)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param startX
|
||||
* @param startZ
|
||||
* @param endX
|
||||
* @param endZ
|
||||
* @return
|
||||
*/
|
||||
public short getAverageDepthOverArea(int startX, int startZ, int endX, int endZ)
|
||||
{
|
||||
int average = 0;
|
||||
|
||||
for(int x = startX; x < endX; x++)
|
||||
for(int z = startZ; z < endZ; z++)
|
||||
average += getDepthForBlockPos(x,z);
|
||||
|
||||
return (short) (average / ((endX - startX) * (endZ - startZ)));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determine the color for each side of this LOD.
|
||||
*/
|
||||
public Color[] getAverageColorOverArea(int startX, int startZ, int endX, int endZ, boolean debugging)
|
||||
{
|
||||
Color[] colors = new Color[ColorDirection.values().length];
|
||||
|
||||
for(int x = startX; x < endX; x++)
|
||||
{
|
||||
for(int z = startZ; z < endZ; z++)
|
||||
{
|
||||
if (!debugging)
|
||||
{
|
||||
// if NOT debugging, look to the config to determine
|
||||
// how this LOD should be colored
|
||||
switch (LodConfig.CLIENT.lodColorStyle.get())
|
||||
{
|
||||
case TOP:
|
||||
// only add the top's color to the array
|
||||
for(ColorDirection dir : ColorDirection.values())
|
||||
colors[dir.value] = getColorForBlockPos(x,z, ColorDirection.TOP);
|
||||
break;
|
||||
|
||||
case INDIVIDUAL_SIDES:
|
||||
// add each direction's color to the array
|
||||
for(ColorDirection dir : ColorDirection.values())
|
||||
colors[dir.value] = getColorForBlockPos(x,z, dir);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if debugging draw the squares as a black and white checker board
|
||||
if ((x + z) % 2 == 0)
|
||||
for(ColorDirection dir : ColorDirection.values())
|
||||
// have each direction be the same
|
||||
// color if debugging
|
||||
colors[dir.value] = DEBUG_WHITE;
|
||||
else
|
||||
for(ColorDirection dir : ColorDirection.values())
|
||||
colors[dir.value] = DEBUG_BLACK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return colors;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Outputs all data in csv format
|
||||
* Outputs all data in a csv format
|
||||
* with the given delimiter.
|
||||
* <br>
|
||||
* Exports data in the form:
|
||||
@@ -286,14 +373,9 @@ public class LodChunk
|
||||
|
||||
s += Integer.toString(x) + DATA_DELIMITER + Integer.toString(z) + DATA_DELIMITER;
|
||||
|
||||
s += Short.toString(height) + DATA_DELIMITER;
|
||||
|
||||
s += Short.toString(depth) + DATA_DELIMITER;
|
||||
|
||||
for(int i = 0; i < colors.length; i++)
|
||||
{
|
||||
s += Integer.toString(colors[i].getRed()) + DATA_DELIMITER + Integer.toString(colors[i].getGreen()) + DATA_DELIMITER + Integer.toString(colors[i].getBlue()) + DATA_DELIMITER;
|
||||
}
|
||||
for (LodDataPoint[] dataPointArray : dataPoints)
|
||||
for(LodDataPoint dataPoint : dataPointArray)
|
||||
s += dataPoint.toData();
|
||||
|
||||
return s;
|
||||
}
|
||||
@@ -306,7 +388,8 @@ public class LodChunk
|
||||
|
||||
s += "x: " + x + " z: " + z + "\t";
|
||||
|
||||
s += "(" + colors[ColorDirection.TOP.value].getRed() + ", " + colors[ColorDirection.TOP.value].getGreen() + ", " + colors[ColorDirection.TOP.value].getBlue() + ")";
|
||||
// TODO
|
||||
//s += "(" + colors[ColorDirection.TOP.value].getRed() + ", " + colors[ColorDirection.TOP.value].getGreen() + ", " + colors[ColorDirection.TOP.value].getBlue() + ")";
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
package com.seibel.lod.objects;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
import com.seibel.lod.enums.ColorDirection;
|
||||
import com.seibel.lod.handlers.LodDimensionFileHandler;
|
||||
|
||||
/**
|
||||
* This stores the height and color
|
||||
* for a specific area in a LodChunk.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 6-12-2021
|
||||
*/
|
||||
public class LodDataPoint
|
||||
{
|
||||
/** This is what separates each piece of data in the toData method */
|
||||
private static final char DATA_DELIMITER = LodDimensionFileHandler.DATA_DELIMITER;
|
||||
|
||||
private static final Color INVISIBLE = new Color(0,0,0,0);
|
||||
|
||||
/** highest point */
|
||||
public short height;
|
||||
|
||||
/** lowest point */
|
||||
public short depth;
|
||||
|
||||
/** The average color for the 6 cardinal directions */
|
||||
public Color colors[];
|
||||
|
||||
|
||||
/**
|
||||
* default constructor
|
||||
*/
|
||||
public LodDataPoint()
|
||||
{
|
||||
height = 0;
|
||||
depth = 0;
|
||||
colors = new Color[ColorDirection.values().length];
|
||||
|
||||
// by default have the colors invisible
|
||||
for(ColorDirection dir : ColorDirection.values())
|
||||
colors[dir.value] = INVISIBLE;
|
||||
}
|
||||
|
||||
|
||||
public LodDataPoint(short newHeight, short newDepth, Color[] newColors)
|
||||
{
|
||||
height = newHeight;
|
||||
depth = newDepth;
|
||||
colors = newColors;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Outputs all data in a csv format
|
||||
* with the given delimiter.
|
||||
* <br>
|
||||
* Exports data in the form:
|
||||
* <br>
|
||||
* height, depth, rgb color data
|
||||
*
|
||||
* <br>
|
||||
* example output:
|
||||
* <br>
|
||||
* 4, 0, 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255, 255,255,255,
|
||||
*/
|
||||
public String toData()
|
||||
{
|
||||
|
||||
String s = Short.toString(height) + DATA_DELIMITER;
|
||||
|
||||
s += Short.toString(depth) + DATA_DELIMITER;
|
||||
|
||||
for(int i = 0; i < colors.length; i++)
|
||||
{
|
||||
s += Integer.toString(colors[i].getRed()) + DATA_DELIMITER + Integer.toString(colors[i].getGreen()) + DATA_DELIMITER + Integer.toString(colors[i].getBlue()) + DATA_DELIMITER;
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ package com.seibel.lod.objects;
|
||||
* one file in the file system.
|
||||
*
|
||||
* @author James Seibel
|
||||
* @version 1-22-2021
|
||||
* @version 6-12-2021
|
||||
*/
|
||||
public class LodRegion
|
||||
{
|
||||
@@ -61,9 +61,6 @@ public class LodRegion
|
||||
int arrayX = Math.abs(chunkX % SIZE);
|
||||
int arrayZ = Math.abs(chunkZ % SIZE);
|
||||
|
||||
if(arrayX >= SIZE || arrayZ >= SIZE)
|
||||
return null;
|
||||
|
||||
return chunks[arrayX][arrayZ];
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user