Fuck fluids

This commit is contained in:
mcrcortex
2024-01-29 17:47:35 +10:00
parent c2c622226b
commit 3cb90f44fc
6 changed files with 134 additions and 363 deletions

View File

@@ -33,18 +33,6 @@ import java.util.*;
//There is strict forward only dataflow //There is strict forward only dataflow
//Ingest -> world engine -> raw render data -> render data //Ingest -> world engine -> raw render data -> render data
public class VoxelCore { public class VoxelCore {
private static final Set<Block> biomeTintableAllFaces = new HashSet<>(List.of(Blocks.OAK_LEAVES, Blocks.JUNGLE_LEAVES, Blocks.ACACIA_LEAVES, Blocks.DARK_OAK_LEAVES, Blocks.VINE, Blocks.MANGROVE_LEAVES,
Blocks.TALL_GRASS, Blocks.LARGE_FERN,
Blocks.SHORT_GRASS,
Blocks.SPRUCE_LEAVES,
Blocks.BIRCH_LEAVES,
Blocks.PINK_PETALS,
Blocks.FERN, Blocks.POTTED_FERN));
private static final Set<Block> biomeTintableUpFace = new HashSet<>(List.of(Blocks.GRASS_BLOCK));
private static final Set<Block> waterTint = new HashSet<>(List.of(Blocks.WATER));
private final WorldEngine world; private final WorldEngine world;
private final DistanceTracker distanceTracker; private final DistanceTracker distanceTracker;
private final RenderGenerationService renderGen; private final RenderGenerationService renderGen;

View File

@@ -7,6 +7,7 @@ import me.cortex.zenith.client.core.gl.GlBuffer;
import me.cortex.zenith.client.core.gl.GlTexture; import me.cortex.zenith.client.core.gl.GlTexture;
import me.cortex.zenith.client.core.rendering.util.UploadStream; import me.cortex.zenith.client.core.rendering.util.UploadStream;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.FluidBlock;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.RenderLayer; import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.RenderLayers; import net.minecraft.client.render.RenderLayers;
@@ -97,6 +98,9 @@ public class ModelManager {
} }
//TODO: what i need to do is seperate out fluid states from blockStates
//TODO: so need a few things, per face sizes and offsets, the sizes should be computed from the pixels and find the minimum bounding pixel //TODO: so need a few things, per face sizes and offsets, the sizes should be computed from the pixels and find the minimum bounding pixel
// while the depth is computed from the depth buffer data // while the depth is computed from the depth buffer data
public int addEntry(int blockId, BlockState blockState) { public int addEntry(int blockId, BlockState blockState) {
@@ -104,8 +108,9 @@ public class ModelManager {
throw new IllegalArgumentException("Trying to add entry for duplicate id"); throw new IllegalArgumentException("Trying to add entry for duplicate id");
} }
boolean isFluid = blockState.getBlock() instanceof FluidBlock;
int modelId = -1; int modelId = -1;
var textureData = this.bakery.renderFaces(blockState, 123456); var textureData = this.bakery.renderFaces(blockState, 123456, isFluid);
{//Deduplicate same entries {//Deduplicate same entries
int possibleDuplicate = this.modelTexture2id.getInt(List.of(textureData)); int possibleDuplicate = this.modelTexture2id.getInt(List.of(textureData));
if (possibleDuplicate != -1) {//Duplicate found if (possibleDuplicate != -1) {//Duplicate found
@@ -122,9 +127,18 @@ public class ModelManager {
var colourProvider = MinecraftClient.getInstance().getBlockColors().providers.get(Registries.BLOCK.getRawId(blockState.getBlock())); var colourProvider = MinecraftClient.getInstance().getBlockColors().providers.get(Registries.BLOCK.getRawId(blockState.getBlock()));
var blockRenderLayer = RenderLayers.getBlockLayer(blockState); RenderLayer blockRenderLayer = null;
if (blockState.getBlock() instanceof FluidBlock) {
blockRenderLayer = RenderLayers.getFluidLayer(blockState.getFluidState());
} else {
blockRenderLayer = RenderLayers.getBlockLayer(blockState);
}
int checkMode = blockRenderLayer==RenderLayer.getSolid()?TextureUtils.WRITE_CHECK_STENCIL:TextureUtils.WRITE_CHECK_ALPHA; int checkMode = blockRenderLayer==RenderLayer.getSolid()?TextureUtils.WRITE_CHECK_STENCIL:TextureUtils.WRITE_CHECK_ALPHA;
//If it is the solid layer, it is _always_ going to occlude fully for all written pixels, even if they are 100% translucent, this should save alot of resources //If it is the solid layer, it is _always_ going to occlude fully for all written pixels, even if they are 100% translucent, this should save alot of resources
// if it is cutout it might occlude might not, need to test // if it is cutout it might occlude might not, need to test
// if it is translucent it will _never_ occlude // if it is translucent it will _never_ occlude
@@ -183,6 +197,7 @@ public class ModelManager {
metadata |= hasBiomeColourResolver?1:0; metadata |= hasBiomeColourResolver?1:0;
metadata |= blockRenderLayer == RenderLayer.getTranslucent()?2:0; metadata |= blockRenderLayer == RenderLayer.getTranslucent()?2:0;
metadata |= needsDoubleSidedQuads?4:0; metadata |= needsDoubleSidedQuads?4:0;
metadata |= (!blockState.getFluidState().isEmpty())?8:0;//Has a fluid state accosiacted with it
//TODO: add a bunch of control config options for overriding/setting options of metadata for each face of each type //TODO: add a bunch of control config options for overriding/setting options of metadata for each face of each type
for (int face = 5; face != -1; face--) {//In reverse order to make indexing into the metadata long easier for (int face = 5; face != -1; face--) {//In reverse order to make indexing into the metadata long easier
@@ -285,6 +300,9 @@ public class ModelManager {
return ((metadata>>(8*6))&2) != 0; return ((metadata>>(8*6))&2) != 0;
} }
public static boolean containsFluid(long metadata) {
return ((metadata>>(8*6))&8) != 0;
}
@@ -316,7 +334,7 @@ public class ModelManager {
public long getModelMetadata(int blockId) { public long getModelMetadata(int blockId) {
int map = this.idMappings[blockId]; int map = this.idMappings[blockId];
if (map == -1) { if (map == -1) {
throw new IllegalArgumentException("Id hasnt been computed yet"); throw new IllegalArgumentException("Id hasnt been computed yet: " + blockId);
} }
return this.metadataCache[map]; return this.metadataCache[map];
} }
@@ -324,7 +342,7 @@ public class ModelManager {
public int getModelId(int blockId) { public int getModelId(int blockId) {
int map = this.idMappings[blockId]; int map = this.idMappings[blockId];
if (map == -1) { if (map == -1) {
throw new IllegalArgumentException("Id hasnt been computed yet"); throw new IllegalArgumentException("Id hasnt been computed yet: " + blockId);
} }
return map; return map;
} }

View File

@@ -10,16 +10,27 @@ import me.cortex.zenith.client.core.gl.shader.Shader;
import me.cortex.zenith.client.core.gl.shader.ShaderLoader; import me.cortex.zenith.client.core.gl.shader.ShaderLoader;
import me.cortex.zenith.client.core.gl.shader.ShaderType; import me.cortex.zenith.client.core.gl.shader.ShaderType;
import me.jellysquid.mods.sodium.client.gl.shader.GlShader; import me.jellysquid.mods.sodium.client.gl.shader.GlShader;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.FluidBlock;
import net.minecraft.block.entity.BlockEntity;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import net.minecraft.client.gl.GlUniform; import net.minecraft.client.gl.GlUniform;
import net.minecraft.client.render.*; import net.minecraft.client.render.*;
import net.minecraft.client.render.model.BakedModel; import net.minecraft.client.render.model.BakedModel;
import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.fluid.FluidState;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import net.minecraft.util.math.RotationAxis; import net.minecraft.util.math.RotationAxis;
import net.minecraft.util.math.random.LocalRandom; import net.minecraft.util.math.random.LocalRandom;
import net.minecraft.world.BlockRenderView;
import net.minecraft.world.LightType;
import net.minecraft.world.biome.ColorResolver;
import net.minecraft.world.chunk.light.LightingProvider;
import org.jetbrains.annotations.Nullable;
import org.joml.Matrix4f; import org.joml.Matrix4f;
import org.lwjgl.opengl.GL11C; import org.lwjgl.opengl.GL11C;
@@ -86,7 +97,7 @@ public class ModelTextureBakery {
//TODO: For block entities, also somehow attempt to render the default block entity, e.g. chests and stuff //TODO: For block entities, also somehow attempt to render the default block entity, e.g. chests and stuff
// cause that will result in ok looking micro details in the terrain // cause that will result in ok looking micro details in the terrain
public ColourDepthTextureData[] renderFaces(BlockState state, long randomValue) { public ColourDepthTextureData[] renderFaces(BlockState state, long randomValue, boolean renderFluid) {
var model = MinecraftClient.getInstance() var model = MinecraftClient.getInstance()
.getBakedModelManager() .getBakedModelManager()
.getBlockModels() .getBlockModels()
@@ -108,7 +119,13 @@ public class ModelTextureBakery {
glBindFramebuffer(GL_FRAMEBUFFER, this.framebuffer.id); glBindFramebuffer(GL_FRAMEBUFFER, this.framebuffer.id);
var renderLayer = RenderLayers.getBlockLayer(state); RenderLayer renderLayer = null;
if (!renderFluid) {
renderLayer = RenderLayers.getBlockLayer(state);
} else {
renderLayer = RenderLayers.getFluidLayer(state.getFluidState());
}
renderLayer.startDrawing(); renderLayer.startDrawing();
glEnable(GL_STENCIL_TEST); glEnable(GL_STENCIL_TEST);
@@ -133,13 +150,10 @@ public class ModelTextureBakery {
//TODO: TRANSLUCENT, must sort the quad first, or something idk //TODO: TRANSLUCENT, must sort the quad first, or something idk
} }
if (!state.getFluidState().isEmpty()) {
//TODO: render fluid
}
var faces = new ColourDepthTextureData[FACE_VIEWS.size()]; var faces = new ColourDepthTextureData[FACE_VIEWS.size()];
for (int i = 0; i < faces.length; i++) { for (int i = 0; i < faces.length; i++) {
faces[i] = captureView(state, model, FACE_VIEWS.get(i), randomValue); faces[i] = captureView(state, model, FACE_VIEWS.get(i), randomValue, i, renderFluid);
//glBlitNamedFramebuffer(this.framebuffer.id, oldFB, 0,0,16,16,300*(i%3),300*(i/3),300*(i%3)+256,300*(i/3)+256, GL_COLOR_BUFFER_BIT, GL_NEAREST); //glBlitNamedFramebuffer(this.framebuffer.id, oldFB, 0,0,16,16,300*(i%3),300*(i/3),300*(i%3)+256,300*(i/3)+256, GL_COLOR_BUFFER_BIT, GL_NEAREST);
} }
@@ -155,17 +169,78 @@ public class ModelTextureBakery {
return faces; return faces;
} }
private ColourDepthTextureData captureView(BlockState state, BakedModel model, MatrixStack stack, long randomValue) { private ColourDepthTextureData captureView(BlockState state, BakedModel model, MatrixStack stack, long randomValue, int face, boolean renderFluid) {
var vc = Tessellator.getInstance().getBuffer(); var vc = Tessellator.getInstance().getBuffer();
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
vc.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE); vc.begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE);
renderQuads(vc, state, model, stack, randomValue);
if (!renderFluid) {
renderQuads(vc, state, model, new MatrixStack(), randomValue);
} else {
MinecraftClient.getInstance().getBlockRenderManager().renderFluid(BlockPos.ORIGIN, new BlockRenderView() {
@Override
public float getBrightness(Direction direction, boolean shaded) {
return 0;
}
@Override
public LightingProvider getLightingProvider() {
return null;
}
@Override
public int getLightLevel(LightType type, BlockPos pos) {
return 0;
}
@Override
public int getColor(BlockPos pos, ColorResolver colorResolver) {
return 0;
}
@Nullable
@Override
public BlockEntity getBlockEntity(BlockPos pos) {
return null;
}
//TODO: make it so it returns air on some positions, e.g. so from UP,
@Override
public BlockState getBlockState(BlockPos pos) {
//TODO:FIXME: Dont hardcode
if (pos.equals(Direction.byId(face).getVector())) {
return Blocks.AIR.getDefaultState();
}
return state;
}
@Override
public FluidState getFluidState(BlockPos pos) {
if (pos.equals(Direction.byId(face).getVector())) {
return Blocks.AIR.getDefaultState().getFluidState();
}
return state.getFluidState();
}
@Override
public int getHeight() {
return 0;
}
@Override
public int getBottomY() {
return 0;
}
}, vc, state, state.getFluidState());
}
float[] mat = new float[4*4]; float[] mat = new float[4*4];
RenderSystem.getProjectionMatrix().get(mat); new Matrix4f(RenderSystem.getProjectionMatrix()).mul(stack.peek().getPositionMatrix()).get(mat);
glUniformMatrix4fv(1, false, mat); glUniformMatrix4fv(1, false, mat);
BufferRenderer.draw(vc.end()); BufferRenderer.draw(vc.end());
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT); glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
int[] colourData = new int[this.width*this.height]; int[] colourData = new int[this.width*this.height];
int[] depthData = new int[this.width*this.height]; int[] depthData = new int[this.width*this.height];

View File

@@ -1,5 +1,6 @@
package me.cortex.zenith.client.core.rendering; package me.cortex.zenith.client.core.rendering;
import com.mojang.blaze3d.platform.GlStateManager;
import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.blaze3d.systems.RenderSystem;
import me.cortex.zenith.client.core.gl.GlBuffer; import me.cortex.zenith.client.core.gl.GlBuffer;
import me.cortex.zenith.client.core.gl.shader.Shader; import me.cortex.zenith.client.core.gl.shader.Shader;
@@ -109,7 +110,7 @@ public class Gl46FarWorldRenderer extends AbstractFarWorldRenderer {
return; return;
} }
//this.models.addEntry(0, Blocks.OAK_FENCE.getDefaultState()); //this.models.addEntry(0, Blocks.STONE.getDefaultState());
RenderLayer.getCutoutMipped().startDrawing(); RenderLayer.getCutoutMipped().startDrawing();
@@ -169,6 +170,8 @@ public class Gl46FarWorldRenderer extends AbstractFarWorldRenderer {
RenderLayer.getTranslucent().startDrawing(); RenderLayer.getTranslucent().startDrawing();
glBindVertexArray(this.vao); glBindVertexArray(this.vao);
glDisable(GL_CULL_FACE); glDisable(GL_CULL_FACE);
RenderSystem.enableBlend();
RenderSystem.blendFuncSeparate(GlStateManager.SrcFactor.SRC_ALPHA, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA, GlStateManager.SrcFactor.ONE, GlStateManager.DstFactor.ONE_MINUS_SRC_ALPHA);
int oldActiveTexture = glGetInteger(GL_ACTIVE_TEXTURE); int oldActiveTexture = glGetInteger(GL_ACTIVE_TEXTURE);
int oldBoundTexture = glGetInteger(GL_TEXTURE_BINDING_2D); int oldBoundTexture = glGetInteger(GL_TEXTURE_BINDING_2D);
@@ -178,14 +181,18 @@ public class Gl46FarWorldRenderer extends AbstractFarWorldRenderer {
glBindTexture(GL_TEXTURE_2D, this.models.getTextureId()); glBindTexture(GL_TEXTURE_2D, this.models.getTextureId());
this.lodShader.bind(); this.lodShader.bind();
glDepthMask(false);
glMultiDrawElementsIndirectCountARB(GL_TRIANGLES, GL_UNSIGNED_SHORT, 400_000 * 4 * 5, 4, this.geometry.getSectionCount(), 0); glMultiDrawElementsIndirectCountARB(GL_TRIANGLES, GL_UNSIGNED_SHORT, 400_000 * 4 * 5, 4, this.geometry.getSectionCount(), 0);
glDepthMask(true);
glEnable(GL_CULL_FACE); glEnable(GL_CULL_FACE);
glBindVertexArray(0); glBindVertexArray(0);
glBindSampler(0, 0); glBindSampler(0, 0);
GL11C.glBindTexture(GL_TEXTURE_2D, oldBoundTexture); GL11C.glBindTexture(GL_TEXTURE_2D, oldBoundTexture);
glActiveTexture(oldActiveTexture); glActiveTexture(oldActiveTexture);
RenderSystem.disableBlend();
RenderLayer.getTranslucent().endDrawing(); RenderLayer.getTranslucent().endDrawing();
} }

View File

@@ -7,6 +7,7 @@ import me.cortex.zenith.common.util.MemoryBuffer;
import me.cortex.zenith.common.world.WorldEngine; import me.cortex.zenith.common.world.WorldEngine;
import me.cortex.zenith.common.world.WorldSection; import me.cortex.zenith.common.world.WorldSection;
import me.cortex.zenith.common.world.other.Mapper; import me.cortex.zenith.common.world.other.Mapper;
import net.minecraft.block.FluidBlock;
import net.minecraft.client.MinecraftClient; import net.minecraft.client.MinecraftClient;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
@@ -210,6 +211,25 @@ public class RenderDataFactory {
return false; return false;
} }
//TODO: if the model has a fluid state, it should compute if a fluid face needs to be injected
// fluid face of type this.world.getMapper().getBlockStateFromId(self).getFluidState() and block type
// this.world.getMapper().getBlockStateFromId(self).getFluidState().getBlockState()
//If we are a fluid and the oposing face is also a fluid need to make a closer check
if (ModelManager.containsFluid(metadata) && ModelManager.containsFluid(facingMetadata)) {
//if (this.world.getMapper().getBlockStateFromId(self).getFluidState() != this.world.getMapper().getBlockStateFromId(facingState).getFluidState()) {
// TODO: need to inject a face here of type fluid, how? i have no god damn idea, probably add an auxilery mesher just for this
//}
//Hackfix
var selfBS = this.world.getMapper().getBlockStateFromId(self);
if (selfBS.getBlock() instanceof FluidBlock && selfBS.getFluidState().getBlockState().getBlock() == this.world.getMapper().getBlockStateFromId(facingState).getFluidState().getBlockState().getBlock()) {
return false;
}
}
int clientModelId = this.modelMan.getModelId(selfBlockId); int clientModelId = this.modelMan.getModelId(selfBlockId);
long otherFlags = 0; long otherFlags = 0;
otherFlags |= ModelManager.isTranslucent(metadata)?1L<<33:0; otherFlags |= ModelManager.isTranslucent(metadata)?1L<<33:0;

View File

@@ -1,337 +0,0 @@
package me.cortex.zenith.client.core.rendering.building;
import it.unimi.dsi.fastutil.longs.LongArrayList;
import me.cortex.zenith.common.util.MemoryBuffer;
import me.cortex.zenith.client.core.util.Mesher2D;
import me.cortex.zenith.common.world.WorldEngine;
import me.cortex.zenith.common.world.WorldSection;
import me.cortex.zenith.common.world.other.Mapper;
import net.minecraft.client.MinecraftClient;
import net.minecraft.util.math.Direction;
import org.lwjgl.system.MemoryUtil;
public class RenderDataFactoryOld {
/*
private final Mesher2D mesher = new Mesher2D(5,15);//15
private final LongArrayList outData = new LongArrayList(1000);
private final WorldEngine world;
private final long[] sectionCache = new long[32*32*32];
private final long[] connectedSectionCache = new long[32*32*32];
private final QuadEncoder encoder;
public RenderDataFactoryOld(WorldEngine world) {
this.world = world;
this.encoder = new QuadEncoder(world.getMapper(), MinecraftClient.getInstance().getBlockColors(), MinecraftClient.getInstance().world);
}
//TODO: MAKE a render cache that caches each WorldSection directional face generation, cause then can just pull that directly
// instead of needing to regen the entire thing
//section is already acquired and gets released by the parent
//buildMask in the lower 6 bits contains the faces to build, the next 6 bits are whether the edge face builds against
// its neigbor or not (0 if it does 1 if it doesnt (0 is default behavior))
public void generateMesh(WorldSection section, int buildMask) {
//TODO: to speed it up more, check like section.isEmpty() and stuff like that, have masks for if a slice/layer is entirly air etc
//TODO: instead of having it check its neighbors with the same lod level, compare against 1 level lower, this will prevent cracks and seams from
// appearing between lods
//if (section.definitelyEmpty()) {//Fast path if its known the entire chunk is empty
// return new BuiltSectionGeometry(section.getKey(), null, null);
//}
section.copyDataTo(this.sectionCache);
var data = this.sectionCache;
long[] connectedData = null;
int dirId = Direction.UP.getId();
if ((buildMask&(1<<dirId))!=0) {
for (int y = 0; y < 32; y++) {
this.mesher.reset();
for (int z = 0; z < 32; z++) {
for (int x = 0; x < 32; x++) {
var self = data[WorldSection.getIndex(x, y, z)];
if (Mapper.isAir(self)) {
continue;
}
long up = -1;
if (y < 31) {
up = data[WorldSection.getIndex(x, y + 1, z)];
if (!Mapper.isTranslucent(up)) {
continue;
}
}
if (y == 31 && ((buildMask>>(6+dirId))&1) == 0) {
//Load and copy the data into a local cache, TODO: optimize so its not doing billion of copies
if (connectedData == null) {
var connectedSection = this.world.acquire(section.lvl, section.x, section.y + 1, section.z);
connectedSection.copyDataTo(this.connectedSectionCache);
connectedData = this.connectedSectionCache;
connectedSection.release();
}
up = connectedData[WorldSection.getIndex(x, 0, z)];
if (!Mapper.isTranslucent(up)) {
continue;
}
}
//Recodes the id to include the correct lighting
this.mesher.put(x, z, (self&~(0xFFL<<56))|(up&(0xFFL<<56)));
}
}
var count = this.mesher.process();
var array = this.mesher.getArray();
for (int i = 0; i < count; i++) {
var quad = array[i];
this.outData.add(this.encoder.encode(this.mesher.getDataFromQuad(quad), 1, y, quad));
}
}
connectedData = null;
}
dirId = Direction.EAST.getId();
if ((buildMask&(1<<dirId))!=0) {
for (int x = 0; x < 32; x++) {
this.mesher.reset();
for (int y = 0; y < 32; y++) {
for (int z = 0; z < 32; z++) {
var self = data[WorldSection.getIndex(x, y, z)];
if (Mapper.isAir(self)) {
continue;
}
long up = -1;
if (x < 31) {
up = data[WorldSection.getIndex(x + 1, y, z)];
if (!Mapper.isTranslucent(up)) {
continue;
}
}
if (x == 31 && ((buildMask>>(6+dirId))&1) == 0) {
//Load and copy the data into a local cache, TODO: optimize so its not doing billion of copies
if (connectedData == null) {
var connectedSection = this.world.acquire(section.lvl, section.x + 1, section.y, section.z);
connectedSection.copyDataTo(this.connectedSectionCache);
connectedData = this.connectedSectionCache;
connectedSection.release();
}
up = connectedData[WorldSection.getIndex(0, y, z)];
if (!Mapper.isTranslucent(up)) {
continue;
}
}
this.mesher.put(y, z, (self&~(0xFFL<<56))|(up&(0xFFL<<56)));
}
}
var count = this.mesher.process();
var array = this.mesher.getArray();
for (int i = 0; i < count; i++) {
var quad = array[i];
this.outData.add(this.encoder.encode(this.mesher.getDataFromQuad(quad), 5, x, quad));
}
}
connectedData = null;
}
dirId = Direction.SOUTH.getId();
if ((buildMask&(1<<dirId))!=0) {
for (int z = 0; z < 32; z++) {
this.mesher.reset();
for (int x = 0; x < 32; x++) {
for (int y = 0; y < 32; y++) {
var self = data[WorldSection.getIndex(x, y, z)];
if (Mapper.isAir(self)) {
continue;
}
long up = -1;
if (z < 31) {
up = data[WorldSection.getIndex(x, y, z + 1)];
if (!Mapper.isTranslucent(up)) {
continue;
}
}
if (z == 31 && ((buildMask>>(6+dirId))&1) == 0) {
//Load and copy the data into a local cache, TODO: optimize so its not doing billion of copies
if (connectedData == null) {
var connectedSection = this.world.acquire(section.lvl, section.x, section.y, section.z + 1);
connectedSection.copyDataTo(this.connectedSectionCache);
connectedData = this.connectedSectionCache;
connectedSection.release();
}
up = connectedData[WorldSection.getIndex(x, y, 0)];
if (!Mapper.isTranslucent(up)) {
continue;
}
}
this.mesher.put(x, y, (self&~(0xFFL<<56))|(up&(0xFFL<<56)));
}
}
var count = this.mesher.process();
var array = this.mesher.getArray();
for (int i = 0; i < count; i++) {
var quad = array[i];
this.outData.add(this.encoder.encode(this.mesher.getDataFromQuad(quad), 3, z, quad));
}
}
connectedData = null;
}
dirId = Direction.WEST.getId();
if ((buildMask&(1<<dirId))!=0) {
for (int x = 31; x != -1; x--) {
this.mesher.reset();
for (int y = 0; y < 32; y++) {
for (int z = 0; z < 32; z++) {
var self = data[WorldSection.getIndex(x, y, z)];
if (Mapper.isAir(self)) {
continue;
}
long up = -1;
if (x != 0) {
up = data[WorldSection.getIndex(x - 1, y, z)];
if (!Mapper.isTranslucent(up)) {
continue;
}
}
if (x == 0 && ((buildMask>>(6+dirId))&1) == 0) {
//Load and copy the data into a local cache, TODO: optimize so its not doing billion of copies
if (connectedData == null) {
var connectedSection = this.world.acquire(section.lvl, section.x - 1, section.y, section.z);
connectedSection.copyDataTo(this.connectedSectionCache);
connectedData = this.connectedSectionCache;
connectedSection.release();
}
up = connectedData[WorldSection.getIndex(31, y, z)];
if (!Mapper.isTranslucent(up)) {
continue;
}
}
this.mesher.put(y, z, (self&~(0xFFL<<56))|(up&(0xFFL<<56)));
}
}
var count = this.mesher.process();
var array = this.mesher.getArray();
for (int i = 0; i < count; i++) {
var quad = array[i];
this.outData.add(this.encoder.encode(this.mesher.getDataFromQuad(quad), 4, x, quad));
}
}
connectedData = null;
}
dirId = Direction.NORTH.getId();
if ((buildMask&(1<<dirId))!=0) {
for (int z = 31; z != -1; z--) {
this.mesher.reset();
for (int x = 0; x < 32; x++) {
for (int y = 0; y < 32; y++) {
var self = data[WorldSection.getIndex(x, y, z)];
if (Mapper.isAir(self)) {
continue;
}
long up = -1;
if (z != 0) {
up = data[WorldSection.getIndex(x, y, z - 1)];
if (!Mapper.isTranslucent(up)) {
continue;
}
}
if (z == 0 && ((buildMask>>(6+dirId))&1) == 0) {
//Load and copy the data into a local cache, TODO: optimize so its not doing billion of copies
if (connectedData == null) {
var connectedSection = this.world.acquire(section.lvl, section.x, section.y, section.z - 1);
connectedSection.copyDataTo(this.connectedSectionCache);
connectedData = this.connectedSectionCache;
connectedSection.release();
}
up = connectedData[WorldSection.getIndex(x, y, 31)];
if (!Mapper.isTranslucent(up)) {
continue;
}
}
this.mesher.put(x, y, (self&~(0xFFL<<56))|(up&(0xFFL<<56)));
}
}
var count = this.mesher.process();
var array = this.mesher.getArray();
for (int i = 0; i < count; i++) {
var quad = array[i];
this.outData.add(this.encoder.encode(this.mesher.getDataFromQuad(quad), 2, z, quad));
}
}
connectedData = null;
}
dirId = Direction.DOWN.getId();
if ((buildMask&(1<<dirId))!=0) {
for (int y = 31; y != -1; y--) {
this.mesher.reset();
for (int x = 0; x < 32; x++) {
for (int z = 0; z < 32; z++) {
var self = data[WorldSection.getIndex(x, y, z)];
if (Mapper.isAir(self)) {
continue;
}
long up = -1;
if (y != 0) {
up = data[WorldSection.getIndex(x, y - 1, z)];
if (!Mapper.isTranslucent(up)) {
continue;
}
}
if (y == 0 && ((buildMask>>(6+dirId))&1) == 0) {
//Load and copy the data into a local cache, TODO: optimize so its not doing billion of copies
if (connectedData == null) {
var connectedSection = this.world.acquire(section.lvl, section.x, section.y - 1, section.z);
connectedSection.copyDataTo(this.connectedSectionCache);
connectedData = this.connectedSectionCache;
connectedSection.release();
}
up = connectedData[WorldSection.getIndex(x, 31, z)];
if (!Mapper.isTranslucent(up)) {
continue;
}
}
this.mesher.put(x, z, (self&~(0xFFL<<56))|(up&(0xFFL<<56)));
}
}
var count = this.mesher.process();
var array = this.mesher.getArray();
for (int i = 0; i < count; i++) {
var quad = array[i];
this.outData.add(this.encoder.encode(this.mesher.getDataFromQuad(quad), 0, y, quad));
}
}
connectedData = null;
}
if (this.outData.isEmpty()) {
//return new BuiltSectionGeometry(section.getKey(), null, null);
}
var output = new MemoryBuffer(this.outData.size()*8L);
for (int i = 0; i < this.outData.size(); i++) {
MemoryUtil.memPutLong(output.address + i * 8L, this.outData.getLong(i));
}
this.outData.clear();
//return new BuiltSectionGeometry(section.getKey(), output, null);
}
*/
}