Optimize ColumnBox building
This commit is contained in:
+120
-80
@@ -23,20 +23,17 @@ import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.enums.EDhDirection;
|
||||
import com.seibel.distanthorizons.core.level.IDhClientLevel;
|
||||
import com.seibel.distanthorizons.core.pooling.PhantomArrayListCheckout;
|
||||
import com.seibel.distanthorizons.core.pooling.PhantomArrayListPool;
|
||||
import com.seibel.distanthorizons.core.render.LodQuadTree;
|
||||
import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.PerfRecorder;
|
||||
import com.seibel.distanthorizons.core.util.RenderDataPointUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.dataObjects.render.columnViews.ColumnArrayView;
|
||||
import com.seibel.distanthorizons.coreapi.util.MathUtil;
|
||||
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class ColumnBox
|
||||
{
|
||||
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
@@ -47,8 +44,6 @@ public class ColumnBox
|
||||
*/
|
||||
private static final byte SKYLIGHT_COVERED = -1;
|
||||
|
||||
public static final PhantomArrayListPool ARRAY_LIST_POOL = new PhantomArrayListPool("Column Box");
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -57,7 +52,7 @@ public class ColumnBox
|
||||
//=========//
|
||||
|
||||
public static void addBoxQuadsToBuilder(
|
||||
LodQuadBuilder builder, IDhClientLevel clientLevel,
|
||||
LodQuadBuilder builder, PhantomArrayListCheckout phantomArrayCheckout, IDhClientLevel clientLevel,
|
||||
short width, short yHeight,
|
||||
short minX, short minY, short minZ,
|
||||
int color, byte irisBlockMaterialId, byte skyLight, byte blockLight,
|
||||
@@ -122,20 +117,26 @@ public class ColumnBox
|
||||
// add top and bottom faces //
|
||||
//==========================//
|
||||
|
||||
boolean skipTop = RenderDataPointUtil.doesDataPointExist(topData)
|
||||
&& (RenderDataPointUtil.getYMin(topData) == maxY)
|
||||
&& !isTopTransparent;
|
||||
if (!skipTop)
|
||||
// top face
|
||||
{
|
||||
builder.addQuadUp(minX, maxY, minZ, width, width, ColorUtil.applyShade(color, MC.getShade(EDhDirection.UP)), irisBlockMaterialId, skyLightTop, blockLight);
|
||||
boolean skipTop = RenderDataPointUtil.doesDataPointExist(topData)
|
||||
&& (RenderDataPointUtil.getYMin(topData) == maxY)
|
||||
&& !isTopTransparent;
|
||||
if (!skipTop)
|
||||
{
|
||||
builder.addQuadUp(minX, maxY, minZ, width, width, ColorUtil.applyShade(color, MC.getShade(EDhDirection.UP)), irisBlockMaterialId, skyLightTop, blockLight);
|
||||
}
|
||||
}
|
||||
|
||||
boolean skipBottom = RenderDataPointUtil.doesDataPointExist(bottomData)
|
||||
&& (RenderDataPointUtil.getYMax(bottomData) == minY)
|
||||
&& !isBottomTransparent;
|
||||
if (!skipBottom)
|
||||
// bottom face
|
||||
{
|
||||
builder.addQuadDown(minX, minY, minZ, width, width, ColorUtil.applyShade(color, MC.getShade(EDhDirection.DOWN)), irisBlockMaterialId, skyLightBot, blockLight);
|
||||
boolean skipBottom = RenderDataPointUtil.doesDataPointExist(bottomData)
|
||||
&& (RenderDataPointUtil.getYMax(bottomData) == minY)
|
||||
&& !isBottomTransparent;
|
||||
if (!skipBottom)
|
||||
{
|
||||
builder.addQuadDown(minX, minY, minZ, width, width, ColorUtil.applyShade(color, MC.getShade(EDhDirection.DOWN)), irisBlockMaterialId, skyLightBot, blockLight);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -146,84 +147,119 @@ public class ColumnBox
|
||||
|
||||
// NORTH face
|
||||
{
|
||||
ColumnArrayView adjCol = adjData[EDhDirection.NORTH.ordinal() - 2]; // TODO can we use something other than ordinal-2?
|
||||
boolean adjSameDetailLevel = isAdjDataSameDetailLevel[EDhDirection.NORTH.ordinal() - 2];
|
||||
ColumnArrayView adjCol = adjData[EDhDirection.NORTH.compassIndex];
|
||||
boolean adjSameDetailLevel = isAdjDataSameDetailLevel[EDhDirection.NORTH.compassIndex];
|
||||
// if the adjacent column is null that generally means the adjacent area hasn't been generated yet
|
||||
if (adjCol == null)
|
||||
{
|
||||
// Add an adjacent face if this is opaque face or transparent over the void.
|
||||
if (!isTransparent || overVoid)
|
||||
{
|
||||
builder.addQuadAdj(EDhDirection.NORTH, minX, minY, minZ, width, yHeight, color, irisBlockMaterialId, LodUtil.MAX_MC_LIGHT, blockLight);
|
||||
builder.addQuadAdj(
|
||||
EDhDirection.NORTH,
|
||||
minX, minY, minZ,
|
||||
width, yHeight,
|
||||
color, irisBlockMaterialId, LodUtil.MAX_MC_LIGHT, blockLight);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
makeAdjVerticalQuad(builder, adjCol, adjSameDetailLevel, caveCullingMaxY, EDhDirection.NORTH, minX, minY, minZ, width, yHeight,
|
||||
makeAdjVerticalQuad(
|
||||
builder, phantomArrayCheckout,
|
||||
adjCol, adjSameDetailLevel, caveCullingMaxY, EDhDirection.NORTH,
|
||||
minX, minY, minZ, width, yHeight,
|
||||
color, irisBlockMaterialId, blockLight);
|
||||
}
|
||||
}
|
||||
|
||||
// SOUTH face
|
||||
{
|
||||
ColumnArrayView adjCol = adjData[EDhDirection.SOUTH.ordinal() - 2];
|
||||
boolean adjSameDetailLevel = isAdjDataSameDetailLevel[EDhDirection.SOUTH.ordinal() - 2];
|
||||
ColumnArrayView adjCol = adjData[EDhDirection.SOUTH.compassIndex];
|
||||
boolean adjSameDetailLevel = isAdjDataSameDetailLevel[EDhDirection.SOUTH.compassIndex];
|
||||
if (adjCol == null)
|
||||
{
|
||||
if (!isTransparent || overVoid)
|
||||
{
|
||||
builder.addQuadAdj(EDhDirection.SOUTH, minX, minY, maxZ, width, yHeight, color, irisBlockMaterialId, LodUtil.MAX_MC_LIGHT, blockLight);
|
||||
builder.addQuadAdj(
|
||||
EDhDirection.SOUTH,
|
||||
minX, minY, maxZ,
|
||||
width, yHeight,
|
||||
color, irisBlockMaterialId, LodUtil.MAX_MC_LIGHT, blockLight);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
makeAdjVerticalQuad(builder, adjCol, adjSameDetailLevel, caveCullingMaxY, EDhDirection.SOUTH, minX, minY, maxZ, width, yHeight,
|
||||
makeAdjVerticalQuad(
|
||||
builder, phantomArrayCheckout,
|
||||
adjCol, adjSameDetailLevel, caveCullingMaxY, EDhDirection.SOUTH,
|
||||
minX, minY, maxZ, width, yHeight,
|
||||
color, irisBlockMaterialId, blockLight);
|
||||
}
|
||||
}
|
||||
|
||||
// WEST face
|
||||
{
|
||||
ColumnArrayView adjCol = adjData[EDhDirection.WEST.ordinal() - 2];
|
||||
boolean adjSameDetailLevel = isAdjDataSameDetailLevel[EDhDirection.WEST.ordinal() - 2];
|
||||
ColumnArrayView adjCol = adjData[EDhDirection.WEST.compassIndex];
|
||||
boolean adjSameDetailLevel = isAdjDataSameDetailLevel[EDhDirection.WEST.compassIndex];
|
||||
if (adjCol == null)
|
||||
{
|
||||
if (!isTransparent || overVoid)
|
||||
{
|
||||
builder.addQuadAdj(EDhDirection.WEST, minX, minY, minZ, width, yHeight, color, irisBlockMaterialId, LodUtil.MAX_MC_LIGHT, blockLight);
|
||||
builder.addQuadAdj(
|
||||
EDhDirection.WEST,
|
||||
minX, minY, minZ,
|
||||
width, yHeight,
|
||||
color, irisBlockMaterialId, LodUtil.MAX_MC_LIGHT, blockLight);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
makeAdjVerticalQuad(builder, adjCol, adjSameDetailLevel, caveCullingMaxY, EDhDirection.WEST, minX, minY, minZ, width, yHeight,
|
||||
makeAdjVerticalQuad(
|
||||
builder, phantomArrayCheckout,
|
||||
adjCol, adjSameDetailLevel, caveCullingMaxY, EDhDirection.WEST,
|
||||
minX, minY, minZ, width, yHeight,
|
||||
color, irisBlockMaterialId, blockLight);
|
||||
}
|
||||
}
|
||||
|
||||
// EAST face
|
||||
{
|
||||
ColumnArrayView adjCol = adjData[EDhDirection.EAST.ordinal() - 2];
|
||||
boolean adjSameDetailLevel = isAdjDataSameDetailLevel[EDhDirection.EAST.ordinal() - 2];
|
||||
ColumnArrayView adjCol = adjData[EDhDirection.EAST.compassIndex];
|
||||
boolean adjSameDetailLevel = isAdjDataSameDetailLevel[EDhDirection.EAST.compassIndex];
|
||||
if (adjCol == null)
|
||||
{
|
||||
if (!isTransparent || overVoid)
|
||||
{
|
||||
builder.addQuadAdj(EDhDirection.EAST, maxX, minY, minZ, width, yHeight, color, irisBlockMaterialId, LodUtil.MAX_MC_LIGHT, blockLight);
|
||||
builder.addQuadAdj(
|
||||
EDhDirection.EAST,
|
||||
maxX, minY, minZ,
|
||||
width, yHeight,
|
||||
color, irisBlockMaterialId, LodUtil.MAX_MC_LIGHT, blockLight);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
makeAdjVerticalQuad(builder, adjCol, adjSameDetailLevel, caveCullingMaxY, EDhDirection.EAST, maxX, minY, minZ, width, yHeight,
|
||||
makeAdjVerticalQuad(
|
||||
builder, phantomArrayCheckout,
|
||||
adjCol, adjSameDetailLevel, caveCullingMaxY, EDhDirection.EAST,
|
||||
maxX, minY, minZ, width, yHeight,
|
||||
color, irisBlockMaterialId, blockLight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void makeAdjVerticalQuad(
|
||||
LodQuadBuilder builder, @NotNull ColumnArrayView adjColumnView, boolean adjacentIsSameDetailLevel, int caveCullingMaxY, EDhDirection direction,
|
||||
LodQuadBuilder builder, PhantomArrayListCheckout phantomArrayCheckout,
|
||||
@NotNull ColumnArrayView adjColumnView, boolean adjacentIsSameDetailLevel, int caveCullingMaxY, EDhDirection direction,
|
||||
short x, short yMin, short z, short horizontalWidth, short ySize,
|
||||
int color, byte irisBlockMaterialId, byte blockLight)
|
||||
{
|
||||
// pooled arrays
|
||||
LongArrayList segments = phantomArrayCheckout.getLongArray(0, 0);
|
||||
LongArrayList newSegments = phantomArrayCheckout.getLongArray(1, 0);
|
||||
|
||||
|
||||
|
||||
//==================//
|
||||
// create face with //
|
||||
// no adjacent data //
|
||||
@@ -240,30 +276,29 @@ public class ColumnBox
|
||||
|
||||
|
||||
|
||||
//===========================//
|
||||
// Build Y-range segments //
|
||||
// with their sky light //
|
||||
//===========================//
|
||||
//=================================//
|
||||
// determine face visibility/light //
|
||||
//=================================//
|
||||
|
||||
boolean transparencyEnabled = Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled;
|
||||
boolean inputTransparent = ColorUtil.getAlpha(color) < 255 && transparencyEnabled;
|
||||
short yMax = (short) (yMin + ySize);
|
||||
|
||||
// List to store segments: [startY, endY, skyLight]
|
||||
ArrayList<YSegment> segments = new ArrayList<>();
|
||||
|
||||
int adjCount = adjColumnView.size();
|
||||
|
||||
// Start with the entire range at max light
|
||||
segments.add(new YSegment(yMin, yMax, LodUtil.MAX_MC_LIGHT));
|
||||
segments.add(YSegmentUtil.encode(yMin, yMax, LodUtil.MAX_MC_LIGHT));
|
||||
|
||||
// Process each adjacent datapoint and split/update segments
|
||||
// Process each adjacent datapoint and split segments as needed
|
||||
for (int adjIndex = 0; adjIndex < adjCount; adjIndex++)
|
||||
{
|
||||
long adjPoint = adjColumnView.get(adjIndex);
|
||||
short adjMinY = RenderDataPointUtil.getYMin(adjPoint);
|
||||
short adjMaxY = RenderDataPointUtil.getYMax(adjPoint);
|
||||
|
||||
// skip empty adjacent points
|
||||
// or points below this one
|
||||
if (!RenderDataPointUtil.doesDataPointExist(adjPoint)
|
||||
|| RenderDataPointUtil.hasZeroHeight(adjPoint)
|
||||
|| yMax <= adjMinY)
|
||||
@@ -271,6 +306,7 @@ public class ColumnBox
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
long adjAbovePoint = (adjIndex != 0) ? adjColumnView.get(adjIndex - 1) : RenderDataPointUtil.EMPTY_DATA;
|
||||
long adjBelowPoint = (adjIndex + 1 < adjCount) ? adjColumnView.get(adjIndex + 1) : RenderDataPointUtil.EMPTY_DATA;
|
||||
|
||||
@@ -306,13 +342,13 @@ public class ColumnBox
|
||||
|
||||
|
||||
// Apply light to the range [adjMinY, adjMaxY)
|
||||
applyLightToRange(segments, adjMinY, adjMaxY, lightToApply);
|
||||
applyLightToRange(segments, newSegments, adjMinY, adjMaxY, lightToApply);
|
||||
|
||||
// Fill overhang area [adjMaxY, adjAboveMinY) with adjSkyLight
|
||||
int adjAboveMinY = RenderDataPointUtil.getYMin(adjAbovePoint);
|
||||
short adjAboveMinY = RenderDataPointUtil.getYMin(adjAbovePoint);
|
||||
if (adjMaxY < adjAboveMinY)
|
||||
{
|
||||
applyLightToRange(segments, adjMaxY, adjAboveMinY, adjSkyLight);
|
||||
applyLightToRange(segments, newSegments, adjMaxY, adjAboveMinY, adjSkyLight);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,27 +359,42 @@ public class ColumnBox
|
||||
// from segments //
|
||||
//=======================//
|
||||
|
||||
for (YSegment seg : segments)
|
||||
for (int i = 0; i < segments.size(); i++)
|
||||
{
|
||||
long segment = segments.getLong(i);
|
||||
tryAddVerticalFaceWithSkyLightToBuilder(
|
||||
builder, direction,
|
||||
x, z, horizontalWidth,
|
||||
color, irisBlockMaterialId, blockLight,
|
||||
seg.skyLight, inputTransparent, seg.endY, seg.startY
|
||||
YSegmentUtil.getSkyLight(segment), inputTransparent, YSegmentUtil.getEndY(segment), YSegmentUtil.getStartY(segment)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Apply a light value to a Y range, splitting segments as needed
|
||||
private static void applyLightToRange(ArrayList<YSegment> segments, int rangeStart, int rangeEnd, byte newLight)
|
||||
/**
|
||||
* Apply the new light value over the given y range,
|
||||
* splitting segments as needed
|
||||
* <p>
|
||||
* source: claude.ai
|
||||
*/
|
||||
private static void applyLightToRange(
|
||||
LongArrayList segments, LongArrayList newSegments,
|
||||
short rangeStart, short rangeEnd,
|
||||
byte newLight)
|
||||
{
|
||||
ArrayList<YSegment> newSegments = new ArrayList<>();
|
||||
// clear the pooled array that the new segments will go into
|
||||
newSegments.clear();
|
||||
|
||||
for (YSegment seg : segments)
|
||||
for (int i = 0; i < segments.size(); i++)
|
||||
{
|
||||
long seg = segments.getLong(i);
|
||||
short endY = YSegmentUtil.getEndY(seg);
|
||||
short startY = YSegmentUtil.getStartY(seg);
|
||||
byte skyLight = YSegmentUtil.getSkyLight(seg);
|
||||
|
||||
// No overlap
|
||||
if (seg.endY <= rangeStart
|
||||
|| seg.startY >= rangeEnd)
|
||||
if (endY <= rangeStart
|
||||
|| startY >= rangeEnd)
|
||||
{
|
||||
newSegments.add(seg);
|
||||
continue;
|
||||
@@ -352,21 +403,21 @@ public class ColumnBox
|
||||
// Partial or complete overlap - need to split
|
||||
|
||||
// Part before the range
|
||||
if (seg.startY < rangeStart)
|
||||
if (startY < rangeStart)
|
||||
{
|
||||
newSegments.add(new YSegment(seg.startY, rangeStart, seg.skyLight));
|
||||
newSegments.add(YSegmentUtil.encode(startY, rangeStart, skyLight));
|
||||
}
|
||||
|
||||
// Overlapping part - take minimum light
|
||||
int overlapStart = Math.max(seg.startY, rangeStart);
|
||||
int overlapEnd = Math.min(seg.endY, rangeEnd);
|
||||
byte minLight = (byte) Math.min(newLight, seg.skyLight);
|
||||
newSegments.add(new YSegment(overlapStart, overlapEnd, minLight));
|
||||
short overlapStart = (short)Math.max(startY, rangeStart);
|
||||
short overlapEnd = (short)Math.min(endY, rangeEnd);
|
||||
byte minLight = (byte) Math.min(newLight, skyLight);
|
||||
newSegments.add(YSegmentUtil.encode(overlapStart, overlapEnd, minLight));
|
||||
|
||||
// Part after the range
|
||||
if (seg.endY > rangeEnd)
|
||||
if (endY > rangeEnd)
|
||||
{
|
||||
newSegments.add(new YSegment(rangeEnd, seg.endY, seg.skyLight));
|
||||
newSegments.add(YSegmentUtil.encode(rangeEnd, endY, skyLight));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -412,23 +463,13 @@ public class ColumnBox
|
||||
|
||||
|
||||
|
||||
private static class YSegment
|
||||
{
|
||||
int startY;
|
||||
int endY;
|
||||
byte skyLight;
|
||||
|
||||
YSegment(int startY, int endY, byte skyLight)
|
||||
{
|
||||
this.startY = startY;
|
||||
this.endY = endY;
|
||||
this.skyLight = skyLight;
|
||||
}
|
||||
}
|
||||
//================//
|
||||
// helper classes //
|
||||
//================//
|
||||
|
||||
|
||||
/**
|
||||
* @see com.seibel.distanthorizons.core.util.FullDataPointUtil
|
||||
/**
|
||||
* encodes height/light data into a long
|
||||
* to reduce object allocations.
|
||||
*/
|
||||
private static class YSegmentUtil
|
||||
{
|
||||
@@ -456,11 +497,10 @@ public class ColumnBox
|
||||
|
||||
public static short getStartY(long data) { return (short) ((data >> START_Y_OFFSET) & START_Y_MASK); }
|
||||
public static short getEndY(long data) { return (short) ((data >> END_Y_OFFSET) & END_Y_MASK); }
|
||||
public static short getSkyLight(long data) { return (short) ((data >> SKY_LIGHT_OFFSET) & SKY_LIGHT_MASK); }
|
||||
public static byte getSkyLight(long data) { return (byte) ((data >> SKY_LIGHT_OFFSET) & SKY_LIGHT_MASK); }
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
+164
-157
@@ -27,6 +27,8 @@ import com.seibel.distanthorizons.core.dataObjects.render.ColumnRenderSource;
|
||||
import com.seibel.distanthorizons.core.level.IDhClientLevel;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.pooling.PhantomArrayListCheckout;
|
||||
import com.seibel.distanthorizons.core.pooling.PhantomArrayListPool;
|
||||
import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos;
|
||||
import com.seibel.distanthorizons.core.pos.DhSectionPos;
|
||||
import com.seibel.distanthorizons.core.render.glObject.GLProxy;
|
||||
@@ -34,7 +36,6 @@ import com.seibel.distanthorizons.core.util.ColorUtil;
|
||||
import com.seibel.distanthorizons.core.util.LodUtil;
|
||||
import com.seibel.distanthorizons.core.util.RenderDataPointUtil;
|
||||
import com.seibel.distanthorizons.core.dataObjects.render.columnViews.ColumnArrayView;
|
||||
import com.seibel.distanthorizons.coreapi.util.BitShiftUtil;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
@@ -47,6 +48,8 @@ public class ColumnRenderBufferBuilder
|
||||
{
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
|
||||
public static final PhantomArrayListPool ARRAY_LIST_POOL = new PhantomArrayListPool("Column Buffer Builder");
|
||||
|
||||
|
||||
|
||||
//==============//
|
||||
@@ -104,182 +107,186 @@ public class ColumnRenderBufferBuilder
|
||||
// build each column //
|
||||
//===================//
|
||||
|
||||
byte thisDetailLevel = renderSource.getDataDetailLevel();
|
||||
for (int relX = 0; relX < ColumnRenderSource.WIDTH; relX++)
|
||||
// pooled arrays for ColumnBox use
|
||||
try (PhantomArrayListCheckout phantomArrayCheckout = ARRAY_LIST_POOL.checkoutArrays(0, 0, 2))
|
||||
{
|
||||
for (int relZ = 0; relZ < ColumnRenderSource.WIDTH; relZ++)
|
||||
byte thisDetailLevel = renderSource.getDataDetailLevel();
|
||||
for (int relX = 0; relX < ColumnRenderSource.WIDTH; relX++)
|
||||
{
|
||||
// ignore empty/null columns
|
||||
ColumnArrayView columnRenderData = renderSource.getVerticalDataPointView(relX, relZ);
|
||||
if (columnRenderData.size() == 0
|
||||
|| !RenderDataPointUtil.doesDataPointExist(columnRenderData.get(0))
|
||||
|| RenderDataPointUtil.hasZeroHeight(columnRenderData.get(0)))
|
||||
for (int relZ = 0; relZ < ColumnRenderSource.WIDTH; relZ++)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// debug limit //
|
||||
//=============//
|
||||
|
||||
// can be used to limit the buffer building to a specific relative position.
|
||||
// useful for debugging a single column
|
||||
if (columnBuilderDebugEnabled)
|
||||
{
|
||||
int wantedX = Config.Client.Advanced.Debugging.ColumnBuilderDebugging.columnBuilderDebugXRow.get();
|
||||
if (wantedX >= 0 && relX != wantedX)
|
||||
// ignore empty/null columns
|
||||
ColumnArrayView columnRenderData = renderSource.getVerticalDataPointView(relX, relZ);
|
||||
if (columnRenderData.size() == 0
|
||||
|| !RenderDataPointUtil.doesDataPointExist(columnRenderData.get(0))
|
||||
|| RenderDataPointUtil.hasZeroHeight(columnRenderData.get(0)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
int wantedZ = Config.Client.Advanced.Debugging.ColumnBuilderDebugging.columnBuilderDebugZRow.get();
|
||||
if (wantedZ >= 0 && relZ != wantedZ)
|
||||
|
||||
|
||||
|
||||
//=============//
|
||||
// debug limit //
|
||||
//=============//
|
||||
|
||||
// can be used to limit the buffer building to a specific relative position.
|
||||
// useful for debugging a single column
|
||||
if (columnBuilderDebugEnabled)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==================================//
|
||||
// get adjacent render data columns //
|
||||
//==================================//
|
||||
|
||||
ColumnArrayView[] adjColumnViews = new ColumnArrayView[EDhDirection.CARDINAL_COMPASS.length];
|
||||
for (EDhDirection lodDirection : EDhDirection.CARDINAL_COMPASS)
|
||||
{
|
||||
try
|
||||
{
|
||||
int xAdj = relX + lodDirection.normal.x;
|
||||
int zAdj = relZ + lodDirection.normal.z;
|
||||
boolean isCrossRenderSourceBoundary =
|
||||
(xAdj < 0 || xAdj >= ColumnRenderSource.WIDTH) ||
|
||||
(zAdj < 0 || zAdj >= ColumnRenderSource.WIDTH);
|
||||
|
||||
ColumnRenderSource adjRenderSource;
|
||||
byte adjDetailLevel;
|
||||
|
||||
|
||||
|
||||
//=========================//
|
||||
// get the adjacent render //
|
||||
// source if present //
|
||||
//=========================//
|
||||
|
||||
if (!isCrossRenderSourceBoundary)
|
||||
int wantedX = Config.Client.Advanced.Debugging.ColumnBuilderDebugging.columnBuilderDebugXRow.get();
|
||||
if (wantedX >= 0 && relX != wantedX)
|
||||
{
|
||||
// the adjacent position is inside this same render source
|
||||
adjRenderSource = renderSource;
|
||||
adjDetailLevel = thisDetailLevel;
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// the adjacent position is outside this render source
|
||||
|
||||
// skip empty sections
|
||||
adjRenderSource = adjRegions[lodDirection.ordinal() - 2];
|
||||
if (adjRenderSource == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
adjDetailLevel = adjRenderSource.getDataDetailLevel();
|
||||
if (adjDetailLevel == thisDetailLevel)
|
||||
{
|
||||
// if the adjacent position is outside this render source,
|
||||
// wrap the position around so it's inside the adjacent source
|
||||
|
||||
if (xAdj < 0)
|
||||
{
|
||||
xAdj += ColumnRenderSource.WIDTH;
|
||||
}
|
||||
if (xAdj >= ColumnRenderSource.WIDTH)
|
||||
{
|
||||
xAdj -= ColumnRenderSource.WIDTH;
|
||||
}
|
||||
|
||||
if (zAdj < 0)
|
||||
{
|
||||
zAdj += ColumnRenderSource.WIDTH;
|
||||
}
|
||||
if (zAdj >= ColumnRenderSource.WIDTH)
|
||||
{
|
||||
zAdj -= ColumnRenderSource.WIDTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//========================//
|
||||
// get the adjacent views //
|
||||
//========================//
|
||||
|
||||
// the old logic handled additional cases, but they never appeared to fire,
|
||||
// so just these two cases should be fine
|
||||
boolean expectedDetailLevels = (adjDetailLevel == thisDetailLevel) || (adjDetailLevel > thisDetailLevel);
|
||||
if (!expectedDetailLevels)
|
||||
{
|
||||
LodUtil.assertNotReach("Mismatch between adjacent detail level ["+adjDetailLevel+"] and this render source's detail level ["+thisDetailLevel+"]. Detail levels should be adj >= this.");
|
||||
}
|
||||
|
||||
adjColumnViews[lodDirection.ordinal() - 2] = adjRenderSource.getVerticalDataPointView(xAdj, zAdj);
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
LOGGER.warn("Failed to get adj data for relative pos: [" + thisDetailLevel + ":" + relX + "," + relZ + "] at [" + lodDirection + "], Error: [" + e.getMessage() + "].", e);
|
||||
}
|
||||
} // for adjacent directions
|
||||
|
||||
|
||||
|
||||
//==========================//
|
||||
// build this render column //
|
||||
//==========================//
|
||||
|
||||
ColumnRenderSource.DebugSourceFlag debugSourceFlag = renderSource.debugGetFlag(relX, relZ);
|
||||
|
||||
for (int i = 0; i < columnRenderData.size(); i++)
|
||||
{
|
||||
// can be uncommented to limit which vertical LOD is generated
|
||||
if (Config.Client.Advanced.Debugging.ColumnBuilderDebugging.columnBuilderDebugEnable.get())
|
||||
{
|
||||
int wantedColumnIndex = Config.Client.Advanced.Debugging.ColumnBuilderDebugging.columnBuilderDebugColumnIndex.get();
|
||||
if (wantedColumnIndex >= 0
|
||||
&& i != wantedColumnIndex)
|
||||
int wantedZ = Config.Client.Advanced.Debugging.ColumnBuilderDebugging.columnBuilderDebugZRow.get();
|
||||
if (wantedZ >= 0 && relZ != wantedZ)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
long data = columnRenderData.get(i);
|
||||
// If the data is not render-able (Void or non-existing) we stop since there is
|
||||
// no data left in this position
|
||||
if (RenderDataPointUtil.hasZeroHeight(data)
|
||||
|| !RenderDataPointUtil.doesDataPointExist(data))
|
||||
|
||||
|
||||
//==================================//
|
||||
// get adjacent render data columns //
|
||||
//==================================//
|
||||
|
||||
ColumnArrayView[] adjColumnViews = new ColumnArrayView[EDhDirection.CARDINAL_COMPASS.length];
|
||||
for (EDhDirection direction : EDhDirection.CARDINAL_COMPASS)
|
||||
{
|
||||
break;
|
||||
try
|
||||
{
|
||||
int xAdj = relX + direction.normal.x;
|
||||
int zAdj = relZ + direction.normal.z;
|
||||
boolean isCrossRenderSourceBoundary =
|
||||
(xAdj < 0 || xAdj >= ColumnRenderSource.WIDTH) ||
|
||||
(zAdj < 0 || zAdj >= ColumnRenderSource.WIDTH);
|
||||
|
||||
ColumnRenderSource adjRenderSource;
|
||||
byte adjDetailLevel;
|
||||
|
||||
|
||||
|
||||
//=========================//
|
||||
// get the adjacent render //
|
||||
// source if present //
|
||||
//=========================//
|
||||
|
||||
if (!isCrossRenderSourceBoundary)
|
||||
{
|
||||
// the adjacent position is inside this same render source
|
||||
adjRenderSource = renderSource;
|
||||
adjDetailLevel = thisDetailLevel;
|
||||
}
|
||||
else
|
||||
{
|
||||
// the adjacent position is outside this render source
|
||||
|
||||
// skip empty sections
|
||||
adjRenderSource = adjRegions[direction.compassIndex];
|
||||
if (adjRenderSource == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
adjDetailLevel = adjRenderSource.getDataDetailLevel();
|
||||
if (adjDetailLevel == thisDetailLevel)
|
||||
{
|
||||
// if the adjacent position is outside this render source,
|
||||
// wrap the position around so it's inside the adjacent source
|
||||
|
||||
if (xAdj < 0)
|
||||
{
|
||||
xAdj += ColumnRenderSource.WIDTH;
|
||||
}
|
||||
if (xAdj >= ColumnRenderSource.WIDTH)
|
||||
{
|
||||
xAdj -= ColumnRenderSource.WIDTH;
|
||||
}
|
||||
|
||||
if (zAdj < 0)
|
||||
{
|
||||
zAdj += ColumnRenderSource.WIDTH;
|
||||
}
|
||||
if (zAdj >= ColumnRenderSource.WIDTH)
|
||||
{
|
||||
zAdj -= ColumnRenderSource.WIDTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//========================//
|
||||
// get the adjacent views //
|
||||
//========================//
|
||||
|
||||
// the old logic handled additional cases, but they never appeared to fire,
|
||||
// so just these two cases should be fine
|
||||
boolean expectedDetailLevels = (adjDetailLevel == thisDetailLevel) || (adjDetailLevel > thisDetailLevel);
|
||||
if (!expectedDetailLevels)
|
||||
{
|
||||
LodUtil.assertNotReach("Mismatch between adjacent detail level ["+adjDetailLevel+"] and this render source's detail level ["+thisDetailLevel+"]. Detail levels should be adj >= this.");
|
||||
}
|
||||
|
||||
adjColumnViews[direction.compassIndex] = adjRenderSource.getVerticalDataPointView(xAdj, zAdj);
|
||||
}
|
||||
catch (RuntimeException e)
|
||||
{
|
||||
LOGGER.warn("Failed to get adj data for relative pos: [" + thisDetailLevel + ":" + relX + "," + relZ + "] at [" + direction + "], Error: [" + e.getMessage() + "].", e);
|
||||
}
|
||||
} // for adjacent directions
|
||||
|
||||
|
||||
|
||||
//==========================//
|
||||
// build this render column //
|
||||
//==========================//
|
||||
|
||||
ColumnRenderSource.DebugSourceFlag debugSourceFlag = renderSource.debugGetFlag(relX, relZ);
|
||||
|
||||
for (int i = 0; i < columnRenderData.size(); i++)
|
||||
{
|
||||
// can be uncommented to limit which vertical LOD is generated
|
||||
if (Config.Client.Advanced.Debugging.ColumnBuilderDebugging.columnBuilderDebugEnable.get())
|
||||
{
|
||||
int wantedColumnIndex = Config.Client.Advanced.Debugging.ColumnBuilderDebugging.columnBuilderDebugColumnIndex.get();
|
||||
if (wantedColumnIndex >= 0
|
||||
&& i != wantedColumnIndex)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
long data = columnRenderData.get(i);
|
||||
// If the data is not render-able (Void or non-existing) we stop since there is
|
||||
// no data left in this position
|
||||
if (RenderDataPointUtil.hasZeroHeight(data)
|
||||
|| !RenderDataPointUtil.doesDataPointExist(data))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
long topDataPoint = (i - 1) >= 0 ? columnRenderData.get(i - 1) : RenderDataPointUtil.EMPTY_DATA;
|
||||
long bottomDataPoint = (i + 1) < columnRenderData.size() ? columnRenderData.get(i + 1) : RenderDataPointUtil.EMPTY_DATA;
|
||||
|
||||
addRenderDataPointToBuilder(
|
||||
clientLevel, phantomArrayCheckout,
|
||||
data, topDataPoint, bottomDataPoint,
|
||||
adjColumnViews, isSameDetailLevel,
|
||||
thisDetailLevel, relX, relZ,
|
||||
quadBuilder, debugSourceFlag);
|
||||
}
|
||||
|
||||
long topDataPoint = (i - 1) >= 0 ? columnRenderData.get(i - 1) : RenderDataPointUtil.EMPTY_DATA;
|
||||
long bottomDataPoint = (i + 1) < columnRenderData.size() ? columnRenderData.get(i + 1) : RenderDataPointUtil.EMPTY_DATA;
|
||||
|
||||
addRenderDataPointToBuilder(
|
||||
clientLevel,
|
||||
data, topDataPoint, bottomDataPoint,
|
||||
adjColumnViews, isSameDetailLevel,
|
||||
thisDetailLevel, relX, relZ,
|
||||
quadBuilder, debugSourceFlag);
|
||||
}
|
||||
|
||||
}// for z
|
||||
}// for x
|
||||
}// for z
|
||||
}// for x
|
||||
}// phantom checkout
|
||||
|
||||
quadBuilder.mergeQuads();
|
||||
}
|
||||
private static void addRenderDataPointToBuilder(
|
||||
IDhClientLevel clientLevel,
|
||||
IDhClientLevel clientLevel, PhantomArrayListCheckout phantomArrayCheckout,
|
||||
long renderData, long topRenderData, long bottomRenderData,
|
||||
ColumnArrayView[] adjColumnViews, boolean[] isSameDetailLevel,
|
||||
byte detailLevel, int renderSourceOffsetPosX, int renderSourceOffsetPosZ,
|
||||
@@ -411,7 +418,7 @@ public class ColumnRenderBufferBuilder
|
||||
}
|
||||
|
||||
ColumnBox.addBoxQuadsToBuilder(
|
||||
quadBuilder, clientLevel,
|
||||
quadBuilder, phantomArrayCheckout, clientLevel,
|
||||
blockWidth, blockMaxY,
|
||||
blockMinX, blockMinY, blockMinZ,
|
||||
color,
|
||||
|
||||
+31
-57
@@ -175,9 +175,7 @@ public class FullDataToRenderDataTransformer
|
||||
ColumnArrayView newColumnArrayView = new ColumnArrayView(dataArrayList, fullDataLength, 0, fullDataLength);
|
||||
setRenderColumnView(levelWrapper, fullDataSource, blockX, blockZ, newColumnArrayView, fullDataColumn);
|
||||
|
||||
PerfRecorder.Timer vertSize = LodQuadTree.TRANSFORM_PERF_RECORDER.start("vertSize");
|
||||
columnArrayView.changeVerticalSizeFrom(newColumnArrayView);
|
||||
vertSize.end();
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -190,8 +188,6 @@ public class FullDataToRenderDataTransformer
|
||||
int blockX, int blockZ,
|
||||
ColumnArrayView renderColumnData, LongArrayList fullColumnData)
|
||||
{
|
||||
PerfRecorder.Timer prep = LodQuadTree.TRANSFORM_PERF_RECORDER.start("prep");
|
||||
|
||||
//===============//
|
||||
// config values //
|
||||
//===============//
|
||||
@@ -223,8 +219,6 @@ public class FullDataToRenderDataTransformer
|
||||
int blocklightToApplyToNextBlock = -1;
|
||||
int renderDataIndex = 0;
|
||||
|
||||
prep.end();
|
||||
|
||||
|
||||
|
||||
//==================================//
|
||||
@@ -238,8 +232,6 @@ public class FullDataToRenderDataTransformer
|
||||
// goes from the top down
|
||||
for (int fullDataIndex = 0; fullDataIndex < fullColumnData.size(); fullDataIndex++)
|
||||
{
|
||||
PerfRecorder.Timer fullParse = LodQuadTree.TRANSFORM_PERF_RECORDER.start("fullParse");
|
||||
|
||||
long fullData = fullColumnData.getLong(fullDataIndex);
|
||||
|
||||
int bottomY = FullDataPointUtil.getBottomY(fullData);
|
||||
@@ -275,8 +267,6 @@ public class FullDataToRenderDataTransformer
|
||||
continue;
|
||||
}
|
||||
|
||||
fullParse.end();
|
||||
|
||||
|
||||
|
||||
//====================//
|
||||
@@ -284,57 +274,48 @@ public class FullDataToRenderDataTransformer
|
||||
// cave culling check //
|
||||
//====================//
|
||||
|
||||
PerfRecorder.Timer caveCull = LodQuadTree.TRANSFORM_PERF_RECORDER.start("caveCull");
|
||||
|
||||
try
|
||||
boolean ignoreBlock = blockStatesToIgnore.contains(block);
|
||||
boolean caveBlock = caveBlockStatesToIgnore.contains(block); // TODO caves should also ignore transparent/non-solid blocks (IE grass and plants) wthout each being defined
|
||||
if (caveBlock)
|
||||
{
|
||||
boolean ignoreBlock = blockStatesToIgnore.contains(block);
|
||||
boolean caveBlock = caveBlockStatesToIgnore.contains(block); // TODO caves should also ignore transparent/non-solid blocks (IE grass and plants) wthout each being defined
|
||||
if (caveBlock)
|
||||
if (caveCullingEnabled
|
||||
// assume this data point is underground if it has no sky-light
|
||||
&& skyLight == LodUtil.MIN_MC_LIGHT
|
||||
// ignore caves above a certain height to prevent floating islands from having walls underneath them
|
||||
&& topY < caveCullingMaxY
|
||||
// cave culling shouldn't happen when at the top of the world
|
||||
&& renderDataIndex != 0 && fullDataIndex != 0
|
||||
// cave culling can't happen when at the bottom of the world
|
||||
&& (fullDataIndex + 1) < fullColumnData.size())
|
||||
{
|
||||
if (caveCullingEnabled
|
||||
// assume this data point is underground if it has no sky-light
|
||||
&& skyLight == LodUtil.MIN_MC_LIGHT
|
||||
// ignore caves above a certain height to prevent floating islands from having walls underneath them
|
||||
&& topY < caveCullingMaxY
|
||||
// cave culling shouldn't happen when at the top of the world
|
||||
&& renderDataIndex != 0 && fullDataIndex != 0
|
||||
// cave culling can't happen when at the bottom of the world
|
||||
&& (fullDataIndex + 1) < fullColumnData.size())
|
||||
// we need to get the next sky/block lights because
|
||||
// the air block here will always have a light of 0/0 due to only the top of the LOD's light being saved.
|
||||
long nextFullData = fullColumnData.getLong(fullDataIndex + 1);
|
||||
int nextSkyLight = FullDataPointUtil.getSkyLight(nextFullData);
|
||||
|
||||
if (nextSkyLight == LodUtil.MIN_MC_LIGHT
|
||||
&& ColorUtil.getAlpha(lastColor) == 255)
|
||||
{
|
||||
// we need to get the next sky/block lights because
|
||||
// the air block here will always have a light of 0/0 due to only the top of the LOD's light being saved.
|
||||
long nextFullData = fullColumnData.getLong(fullDataIndex + 1);
|
||||
int nextSkyLight = FullDataPointUtil.getSkyLight(nextFullData);
|
||||
|
||||
if (nextSkyLight == LodUtil.MIN_MC_LIGHT
|
||||
&& ColorUtil.getAlpha(lastColor) == 255)
|
||||
{
|
||||
// replace the previous block with new bottom
|
||||
long columnData = renderColumnData.get(renderDataIndex - 1);
|
||||
columnData = RenderDataPointUtil.setYMin(columnData, bottomY);
|
||||
renderColumnData.set(renderDataIndex - 1, columnData);
|
||||
}
|
||||
|
||||
continue;
|
||||
// replace the previous block with new bottom
|
||||
long columnData = renderColumnData.get(renderDataIndex - 1);
|
||||
columnData = RenderDataPointUtil.setYMin(columnData, bottomY);
|
||||
renderColumnData.set(renderDataIndex - 1, columnData);
|
||||
}
|
||||
|
||||
|
||||
if (ignoreBlock)
|
||||
{
|
||||
// this is a merged block and a cave block, so it should never be rendered
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
else if (ignoreBlock)
|
||||
|
||||
|
||||
if (ignoreBlock)
|
||||
{
|
||||
// this is an ignored block, but shouldn't be merged like a cave block
|
||||
// this is a merged block and a cave block, so it should never be rendered
|
||||
continue;
|
||||
}
|
||||
}
|
||||
finally
|
||||
else if (ignoreBlock)
|
||||
{
|
||||
caveCull.end();
|
||||
// this is an ignored block, but shouldn't be merged like a cave block
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
@@ -350,9 +331,7 @@ public class FullDataToRenderDataTransformer
|
||||
{
|
||||
if (colorBelowWithAvoidedBlocks)
|
||||
{
|
||||
PerfRecorder.Timer nonSolid = LodQuadTree.TRANSFORM_PERF_RECORDER.start("color-NonSolid");
|
||||
int tempColor = levelWrapper.getBlockColor(mutableBlockPos, biome, fullDataSource, block);
|
||||
nonSolid.end();
|
||||
|
||||
// don't transfer the color when alpha is 0
|
||||
// this prevents issues if grass is transparent
|
||||
@@ -372,10 +351,8 @@ public class FullDataToRenderDataTransformer
|
||||
int color;
|
||||
if (colorToApplyToNextBlock == -1)
|
||||
{
|
||||
PerfRecorder.Timer colorTimer = LodQuadTree.TRANSFORM_PERF_RECORDER.start("color");
|
||||
// use this block's color
|
||||
color = levelWrapper.getBlockColor(mutableBlockPos, biome, fullDataSource, block);
|
||||
colorTimer.end();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -391,7 +368,6 @@ public class FullDataToRenderDataTransformer
|
||||
//=============================//
|
||||
// merge same-colored adjacent //
|
||||
//=============================//
|
||||
PerfRecorder.Timer mergeSame = LodQuadTree.TRANSFORM_PERF_RECORDER.start("mergeSame");
|
||||
|
||||
// check if they share a top-bottom face and if they have same color
|
||||
if (color == lastColor
|
||||
@@ -413,8 +389,6 @@ public class FullDataToRenderDataTransformer
|
||||
}
|
||||
lastBottom = bottomY;
|
||||
lastColor = color;
|
||||
|
||||
mergeSame.end();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -97,8 +97,6 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
|
||||
// TODO should be removed once James is done testing
|
||||
@Deprecated
|
||||
public static final PerfRecorder FILE_PERF_RECORDER = new PerfRecorder("File");
|
||||
@Deprecated
|
||||
public static final PerfRecorder TRANSFORM_PERF_RECORDER = new PerfRecorder("Transform");
|
||||
|
||||
/** the smallest numerical detail level number that can be rendered */
|
||||
private byte maxLeafRenderDetailLevel;
|
||||
@@ -133,8 +131,6 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
|
||||
this.beaconRenderHandler = (genericObjectRenderer != null) ? new BeaconRenderHandler(genericObjectRenderer) : null;
|
||||
|
||||
FILE_PERF_RECORDER.clear();
|
||||
TRANSFORM_PERF_RECORDER.clear();
|
||||
COL_BOX_PERF_RECORDER.clear();
|
||||
|
||||
}
|
||||
|
||||
@@ -160,8 +156,6 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
|
||||
|
||||
|
||||
FILE_PERF_RECORDER.tryLog();
|
||||
TRANSFORM_PERF_RECORDER.tryLog();
|
||||
COL_BOX_PERF_RECORDER.tryLog();
|
||||
|
||||
|
||||
// this shouldn't be updated while the tree is being iterated through
|
||||
|
||||
@@ -287,16 +287,16 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable
|
||||
ColumnRenderSource westRenderSource = adjacentLoadFutures[3].get())
|
||||
{
|
||||
ColumnRenderSource[] adjacentRenderSections = new ColumnRenderSource[EDhDirection.CARDINAL_COMPASS.length];
|
||||
adjacentRenderSections[EDhDirection.NORTH.ordinal() - 2] = northRenderSource;
|
||||
adjacentRenderSections[EDhDirection.SOUTH.ordinal() - 2] = southRenderSource;
|
||||
adjacentRenderSections[EDhDirection.EAST.ordinal() - 2] = eastRenderSource;
|
||||
adjacentRenderSections[EDhDirection.WEST.ordinal() - 2] = westRenderSource;
|
||||
adjacentRenderSections[EDhDirection.NORTH.compassIndex] = northRenderSource;
|
||||
adjacentRenderSections[EDhDirection.SOUTH.compassIndex] = southRenderSource;
|
||||
adjacentRenderSections[EDhDirection.EAST.compassIndex] = eastRenderSource;
|
||||
adjacentRenderSections[EDhDirection.WEST.compassIndex] = westRenderSource;
|
||||
|
||||
boolean[] adjIsSameDetailLevel = new boolean[EDhDirection.CARDINAL_COMPASS.length];
|
||||
adjIsSameDetailLevel[EDhDirection.NORTH.ordinal() - 2] = this.isAdjacentPosSameDetailLevel(EDhDirection.NORTH);
|
||||
adjIsSameDetailLevel[EDhDirection.SOUTH.ordinal() - 2] = this.isAdjacentPosSameDetailLevel(EDhDirection.SOUTH);
|
||||
adjIsSameDetailLevel[EDhDirection.EAST.ordinal() - 2] = this.isAdjacentPosSameDetailLevel(EDhDirection.EAST);
|
||||
adjIsSameDetailLevel[EDhDirection.WEST.ordinal() - 2] = this.isAdjacentPosSameDetailLevel(EDhDirection.WEST);
|
||||
adjIsSameDetailLevel[EDhDirection.NORTH.compassIndex] = this.isAdjacentPosSameDetailLevel(EDhDirection.NORTH);
|
||||
adjIsSameDetailLevel[EDhDirection.SOUTH.compassIndex] = this.isAdjacentPosSameDetailLevel(EDhDirection.SOUTH);
|
||||
adjIsSameDetailLevel[EDhDirection.EAST.compassIndex] = this.isAdjacentPosSameDetailLevel(EDhDirection.EAST);
|
||||
adjIsSameDetailLevel[EDhDirection.WEST.compassIndex] = this.isAdjacentPosSameDetailLevel(EDhDirection.WEST);
|
||||
|
||||
// the render sources are only needed by this synchronous method,
|
||||
// then they can be closed
|
||||
|
||||
Reference in New Issue
Block a user