Fuck fluids
This commit is contained in:
@@ -33,18 +33,6 @@ import java.util.*;
|
||||
//There is strict forward only dataflow
|
||||
//Ingest -> world engine -> raw render data -> render data
|
||||
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 DistanceTracker distanceTracker;
|
||||
private final RenderGenerationService renderGen;
|
||||
|
||||
@@ -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.rendering.util.UploadStream;
|
||||
import net.minecraft.block.BlockState;
|
||||
import net.minecraft.block.FluidBlock;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.render.RenderLayer;
|
||||
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
|
||||
// while the depth is computed from the depth buffer data
|
||||
public int addEntry(int blockId, BlockState blockState) {
|
||||
@@ -104,8 +108,9 @@ public class ModelManager {
|
||||
throw new IllegalArgumentException("Trying to add entry for duplicate id");
|
||||
}
|
||||
|
||||
boolean isFluid = blockState.getBlock() instanceof FluidBlock;
|
||||
int modelId = -1;
|
||||
var textureData = this.bakery.renderFaces(blockState, 123456);
|
||||
var textureData = this.bakery.renderFaces(blockState, 123456, isFluid);
|
||||
{//Deduplicate same entries
|
||||
int possibleDuplicate = this.modelTexture2id.getInt(List.of(textureData));
|
||||
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 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;
|
||||
|
||||
|
||||
|
||||
//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 translucent it will _never_ occlude
|
||||
@@ -183,6 +197,7 @@ public class ModelManager {
|
||||
metadata |= hasBiomeColourResolver?1:0;
|
||||
metadata |= blockRenderLayer == RenderLayer.getTranslucent()?2: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
|
||||
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;
|
||||
}
|
||||
|
||||
public static boolean containsFluid(long metadata) {
|
||||
return ((metadata>>(8*6))&8) != 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -316,7 +334,7 @@ public class ModelManager {
|
||||
public long getModelMetadata(int blockId) {
|
||||
int map = this.idMappings[blockId];
|
||||
if (map == -1) {
|
||||
throw new IllegalArgumentException("Id hasnt been computed yet");
|
||||
throw new IllegalArgumentException("Id hasnt been computed yet: " + blockId);
|
||||
}
|
||||
return this.metadataCache[map];
|
||||
}
|
||||
@@ -324,7 +342,7 @@ public class ModelManager {
|
||||
public int getModelId(int blockId) {
|
||||
int map = this.idMappings[blockId];
|
||||
if (map == -1) {
|
||||
throw new IllegalArgumentException("Id hasnt been computed yet");
|
||||
throw new IllegalArgumentException("Id hasnt been computed yet: " + blockId);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@@ -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.ShaderType;
|
||||
import me.jellysquid.mods.sodium.client.gl.shader.GlShader;
|
||||
import net.minecraft.block.Block;
|
||||
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.gl.GlUniform;
|
||||
import net.minecraft.client.render.*;
|
||||
import net.minecraft.client.render.model.BakedModel;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.fluid.FluidState;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Direction;
|
||||
import net.minecraft.util.math.RotationAxis;
|
||||
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.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
|
||||
// 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()
|
||||
.getBakedModelManager()
|
||||
.getBlockModels()
|
||||
@@ -108,7 +119,13 @@ public class ModelTextureBakery {
|
||||
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();
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
@@ -133,13 +150,10 @@ public class ModelTextureBakery {
|
||||
//TODO: TRANSLUCENT, must sort the quad first, or something idk
|
||||
}
|
||||
|
||||
if (!state.getFluidState().isEmpty()) {
|
||||
//TODO: render fluid
|
||||
}
|
||||
|
||||
var faces = new ColourDepthTextureData[FACE_VIEWS.size()];
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -155,17 +169,78 @@ public class ModelTextureBakery {
|
||||
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();
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
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];
|
||||
RenderSystem.getProjectionMatrix().get(mat);
|
||||
new Matrix4f(RenderSystem.getProjectionMatrix()).mul(stack.peek().getPositionMatrix()).get(mat);
|
||||
glUniformMatrix4fv(1, false, mat);
|
||||
BufferRenderer.draw(vc.end());
|
||||
|
||||
|
||||
glMemoryBarrier(GL_FRAMEBUFFER_BARRIER_BIT);
|
||||
int[] colourData = new int[this.width*this.height];
|
||||
int[] depthData = new int[this.width*this.height];
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package me.cortex.zenith.client.core.rendering;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import me.cortex.zenith.client.core.gl.GlBuffer;
|
||||
import me.cortex.zenith.client.core.gl.shader.Shader;
|
||||
@@ -109,7 +110,7 @@ public class Gl46FarWorldRenderer extends AbstractFarWorldRenderer {
|
||||
return;
|
||||
}
|
||||
|
||||
//this.models.addEntry(0, Blocks.OAK_FENCE.getDefaultState());
|
||||
//this.models.addEntry(0, Blocks.STONE.getDefaultState());
|
||||
|
||||
|
||||
RenderLayer.getCutoutMipped().startDrawing();
|
||||
@@ -169,6 +170,8 @@ public class Gl46FarWorldRenderer extends AbstractFarWorldRenderer {
|
||||
RenderLayer.getTranslucent().startDrawing();
|
||||
glBindVertexArray(this.vao);
|
||||
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 oldBoundTexture = glGetInteger(GL_TEXTURE_BINDING_2D);
|
||||
@@ -178,14 +181,18 @@ public class Gl46FarWorldRenderer extends AbstractFarWorldRenderer {
|
||||
glBindTexture(GL_TEXTURE_2D, this.models.getTextureId());
|
||||
this.lodShader.bind();
|
||||
|
||||
glDepthMask(false);
|
||||
glMultiDrawElementsIndirectCountARB(GL_TRIANGLES, GL_UNSIGNED_SHORT, 400_000 * 4 * 5, 4, this.geometry.getSectionCount(), 0);
|
||||
glDepthMask(true);
|
||||
|
||||
glEnable(GL_CULL_FACE);
|
||||
glBindVertexArray(0);
|
||||
|
||||
|
||||
glBindSampler(0, 0);
|
||||
GL11C.glBindTexture(GL_TEXTURE_2D, oldBoundTexture);
|
||||
glActiveTexture(oldActiveTexture);
|
||||
RenderSystem.disableBlend();
|
||||
|
||||
RenderLayer.getTranslucent().endDrawing();
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ import me.cortex.zenith.common.util.MemoryBuffer;
|
||||
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.block.FluidBlock;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import org.lwjgl.system.MemoryUtil;
|
||||
|
||||
@@ -210,6 +211,25 @@ public class RenderDataFactory {
|
||||
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);
|
||||
long otherFlags = 0;
|
||||
otherFlags |= ModelManager.isTranslucent(metadata)?1L<<33:0;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user