From 57c0e7daf73433a1c4439218c374d5350c90cfbc Mon Sep 17 00:00:00 2001 From: mcrcortex <18544518+MCRcortex@users.noreply.github.com> Date: Tue, 16 Jan 2024 11:16:29 +1000 Subject: [PATCH] WIP --- .../voxelmon/core/rendering/ModelManager.java | 5 + .../rendering/building/ColourMapping.java | 9 ++ .../core/rendering/building/QuadEncoder.java | 82 ++++++++++++++++ .../core/rendering/building/QuadFormat.java | 94 ------------------- .../rendering/building/RenderDataFactory.java | 18 ++-- .../voxelmon/core/world/other/Mapper.java | 6 ++ 6 files changed, 113 insertions(+), 101 deletions(-) create mode 100644 src/main/java/me/cortex/voxelmon/core/rendering/ModelManager.java create mode 100644 src/main/java/me/cortex/voxelmon/core/rendering/building/ColourMapping.java create mode 100644 src/main/java/me/cortex/voxelmon/core/rendering/building/QuadEncoder.java delete mode 100644 src/main/java/me/cortex/voxelmon/core/rendering/building/QuadFormat.java diff --git a/src/main/java/me/cortex/voxelmon/core/rendering/ModelManager.java b/src/main/java/me/cortex/voxelmon/core/rendering/ModelManager.java new file mode 100644 index 00000000..99242ae5 --- /dev/null +++ b/src/main/java/me/cortex/voxelmon/core/rendering/ModelManager.java @@ -0,0 +1,5 @@ +package me.cortex.voxelmon.core.rendering; + +//Manages the storage and updating of model states, textures and colours +public class ModelManager { +} diff --git a/src/main/java/me/cortex/voxelmon/core/rendering/building/ColourMapping.java b/src/main/java/me/cortex/voxelmon/core/rendering/building/ColourMapping.java new file mode 100644 index 00000000..dcf96986 --- /dev/null +++ b/src/main/java/me/cortex/voxelmon/core/rendering/building/ColourMapping.java @@ -0,0 +1,9 @@ +package me.cortex.voxelmon.core.rendering.building; + +//Class for generating holding and remapping colours and ids +// used during building and then remapping into the global colour array before insertion into the world +public class ColourMapping { + public void reset() { + + } +} diff --git a/src/main/java/me/cortex/voxelmon/core/rendering/building/QuadEncoder.java b/src/main/java/me/cortex/voxelmon/core/rendering/building/QuadEncoder.java new file mode 100644 index 00000000..65abf48f --- /dev/null +++ b/src/main/java/me/cortex/voxelmon/core/rendering/building/QuadEncoder.java @@ -0,0 +1,82 @@ +package me.cortex.voxelmon.core.rendering.building; + + +import me.cortex.voxelmon.core.util.Mesher2D; +import me.cortex.voxelmon.core.world.other.Mapper; +import net.minecraft.client.color.block.BlockColors; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.util.math.BlockPos; + + +public class QuadEncoder { + private final BlockColors colourProvider; + private final Mapper mapper; + private final ClientWorld worldIn; + public QuadEncoder(Mapper mapper, BlockColors colourProvider, ClientWorld worldIn) { + this.colourProvider = colourProvider; + this.mapper = mapper; + this.worldIn = worldIn; + } + + //Normalize block states that result in the same output state, (this improves meshing) + // such as the 8 different types of leaves (due to distance from wood) should get normalized to 1 type + // if the textures are the same + public long normalizeBlockState(long id) { + //TODO: This + return id; + } + + private int getColour(long id, int x, int y, int z) { + //TODO: need to inject the biome somehow + return this.colourProvider.getColor(this.mapper.getBlockStateFromId(id), this.worldIn, new BlockPos(x, y, z), 0); + } + + //The way it works is that, when encoding, use a local colour mapping, then it remaps later to a global colour store + public long encode(long id, int face, int otherAxis, int encodedMeshedData) { + int encodePosition = encodePosition(face, otherAxis, encodedMeshedData);//26 bits + int lighting = (int) ((id>>56)&0xFF);//8 bits + + int biome = (int) ((id>>47)&((1<<9)-1)); + int blockstate = (int) ((id>>20)&((1<<20)-1)); + + int blockColour = this.getColour(id, -1, -1, -1); + // if blockColour is -1 it means it doesnt have colour + + return -1; + } + + + + + //Note: the encodedMeshedData is from the Mesher2D + public static int encodePosition(int face, int otherAxis, int encodedMeshedData) { + if (Mesher2D.getW(encodedMeshedData) > 16 || Mesher2D.getH(encodedMeshedData) > 16) { + throw new IllegalStateException("Width or height > 16"); + } + int out = face; + out |= switch (face >> 1) { + case 0 -> + (Mesher2D.getX(encodedMeshedData) << 21) | + (otherAxis << 16) | + (Mesher2D.getZ(encodedMeshedData) << 11) | + ((Mesher2D.getW(encodedMeshedData)-1) << 7) | + ((Mesher2D.getH(encodedMeshedData)-1) << 3); + + case 1 -> + (Mesher2D.getX(encodedMeshedData) << 21) | + (Mesher2D.getZ(encodedMeshedData) << 16) | + (otherAxis << 11) | + ((Mesher2D.getW(encodedMeshedData)-1) << 7) | + ((Mesher2D.getH(encodedMeshedData)-1) << 3); + + case 2 -> + (otherAxis << 21) | + (Mesher2D.getX(encodedMeshedData) << 16) | + (Mesher2D.getZ(encodedMeshedData) << 11) | + ((Mesher2D.getW(encodedMeshedData)-1) << 7) | + ((Mesher2D.getH(encodedMeshedData)-1) << 3); + default -> throw new IllegalStateException("Unexpected value: " + (face >> 1)); + }; + return out; + } +} diff --git a/src/main/java/me/cortex/voxelmon/core/rendering/building/QuadFormat.java b/src/main/java/me/cortex/voxelmon/core/rendering/building/QuadFormat.java deleted file mode 100644 index bca48afd..00000000 --- a/src/main/java/me/cortex/voxelmon/core/rendering/building/QuadFormat.java +++ /dev/null @@ -1,94 +0,0 @@ -package me.cortex.voxelmon.core.rendering.building; - - -import me.cortex.voxelmon.core.util.Mesher2D; -import me.cortex.voxelmon.core.world.other.Mapper; - -/* -8 - Light (can probably make it 3,3 bit lighting then i get 2 spare bits for other things) - -8 - R -8 - G -8 - B -4 - A - -5 - x -5 - y -5 - z -4 - w -4 - h -3 - face - */ - - -//TODO: might be able to fit it within 32 bits _very hackily_ (keep the same position data) -// but then have a per section LUT - - -//V2 QUAD FORMAT (enables animations to work) -/* -1 - spare -8 - light -9 - biome id -20 - block id -5 - x -5 - y -5 - z -4 - w -4 - h -3 - face - */ - -public class QuadFormat { - //Note: the encodedMeshedData is from the Mesher2D - public static int encodePosition(int face, int otherAxis, int encodedMeshedData) { - if (Mesher2D.getW(encodedMeshedData) > 16 || Mesher2D.getH(encodedMeshedData) > 16) { - throw new IllegalStateException("Width or height > 16"); - } - int out = face; - out |= switch (face >> 1) { - case 0 -> - (Mesher2D.getX(encodedMeshedData) << 21) | - (otherAxis << 16) | - (Mesher2D.getZ(encodedMeshedData) << 11) | - ((Mesher2D.getW(encodedMeshedData)-1) << 7) | - ((Mesher2D.getH(encodedMeshedData)-1) << 3); - - case 1 -> - (Mesher2D.getX(encodedMeshedData) << 21) | - (Mesher2D.getZ(encodedMeshedData) << 16) | - (otherAxis << 11) | - ((Mesher2D.getW(encodedMeshedData)-1) << 7) | - ((Mesher2D.getH(encodedMeshedData)-1) << 3); - - case 2 -> - (otherAxis << 21) | - (Mesher2D.getX(encodedMeshedData) << 16) | - (Mesher2D.getZ(encodedMeshedData) << 11) | - ((Mesher2D.getW(encodedMeshedData)-1) << 7) | - ((Mesher2D.getH(encodedMeshedData)-1) << 3); - default -> throw new IllegalStateException("Unexpected value: " + (face >> 1)); - }; - return out; - } - - //TODO: finish - public static long encode(Mapper mapper, long id, int encodedPosition) { - return ((id>>>27)<<26)|Integer.toUnsignedLong(encodedPosition); - } - - public static long encode(Mapper mapper, long id, int face, int otherAxis, int encodedMeshedData) { - return encode(mapper, id, encodePosition(face, otherAxis, encodedMeshedData)); - } - - - - private static long encodeV2(Mapper mapper, long id, int face, int otherAxis, int encodedMeshedData) { - int position = encodePosition(face, otherAxis, encodedMeshedData); - int lighting = (int) ((id>>56)&0xFF); - int biome = (int) ((id>>47)&((1<<9)-1)); - int blockstate = (int) ((id>>20)&((1<<20)-1)); - - return -1; - } -} diff --git a/src/main/java/me/cortex/voxelmon/core/rendering/building/RenderDataFactory.java b/src/main/java/me/cortex/voxelmon/core/rendering/building/RenderDataFactory.java index ef3a6037..a76275e3 100644 --- a/src/main/java/me/cortex/voxelmon/core/rendering/building/RenderDataFactory.java +++ b/src/main/java/me/cortex/voxelmon/core/rendering/building/RenderDataFactory.java @@ -6,6 +6,7 @@ import me.cortex.voxelmon.core.util.Mesher2D; import me.cortex.voxelmon.core.world.WorldEngine; import me.cortex.voxelmon.core.world.WorldSection; import me.cortex.voxelmon.core.world.other.Mapper; +import net.minecraft.client.MinecraftClient; import net.minecraft.util.math.Direction; import org.lwjgl.system.MemoryUtil; @@ -16,9 +17,11 @@ public class RenderDataFactory { private final WorldEngine world; private final long[] sectionCache = new long[32*32*32]; private final long[] connectedSectionCache = new long[32*32*32]; - + private final ColourMapping colourCache = new ColourMapping(); + private final QuadEncoder encoder; public RenderDataFactory(WorldEngine world) { this.world = world; + this.encoder = new QuadEncoder(world.getMapper(), MinecraftClient.getInstance().getBlockColors(), MinecraftClient.getInstance().world); } @@ -31,6 +34,7 @@ public class RenderDataFactory { //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 BuiltSectionGeometry generateMesh(WorldSection section, int buildMask) { + this.colourCache.reset(); //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 @@ -85,7 +89,7 @@ public class RenderDataFactory { var array = this.mesher.getArray(); for (int i = 0; i < count; i++) { var quad = array[i]; - this.outData.add(QuadFormat.encode(null, this.mesher.getDataFromQuad(quad), 1, y, quad)); + this.outData.add(this.encoder.encode(this.mesher.getDataFromQuad(quad), 1, y, quad)); } } connectedData = null; @@ -130,7 +134,7 @@ public class RenderDataFactory { var array = this.mesher.getArray(); for (int i = 0; i < count; i++) { var quad = array[i]; - this.outData.add(QuadFormat.encode(null, this.mesher.getDataFromQuad(quad), 5, x, quad)); + this.outData.add(this.encoder.encode(this.mesher.getDataFromQuad(quad), 5, x, quad)); } } connectedData = null; @@ -175,7 +179,7 @@ public class RenderDataFactory { var array = this.mesher.getArray(); for (int i = 0; i < count; i++) { var quad = array[i]; - this.outData.add(QuadFormat.encode(null, this.mesher.getDataFromQuad(quad), 3, z, quad)); + this.outData.add(this.encoder.encode(this.mesher.getDataFromQuad(quad), 3, z, quad)); } } connectedData = null; @@ -220,7 +224,7 @@ public class RenderDataFactory { var array = this.mesher.getArray(); for (int i = 0; i < count; i++) { var quad = array[i]; - this.outData.add(QuadFormat.encode(null, this.mesher.getDataFromQuad(quad), 4, x, quad)); + this.outData.add(this.encoder.encode(this.mesher.getDataFromQuad(quad), 4, x, quad)); } } connectedData = null; @@ -265,7 +269,7 @@ public class RenderDataFactory { var array = this.mesher.getArray(); for (int i = 0; i < count; i++) { var quad = array[i]; - this.outData.add(QuadFormat.encode(null, this.mesher.getDataFromQuad(quad), 2, z, quad)); + this.outData.add(this.encoder.encode(this.mesher.getDataFromQuad(quad), 2, z, quad)); } } connectedData = null; @@ -310,7 +314,7 @@ public class RenderDataFactory { var array = this.mesher.getArray(); for (int i = 0; i < count; i++) { var quad = array[i]; - this.outData.add(QuadFormat.encode(null, this.mesher.getDataFromQuad(quad), 0, y, quad)); + this.outData.add(this.encoder.encode(this.mesher.getDataFromQuad(quad), 0, y, quad)); } } connectedData = null; diff --git a/src/main/java/me/cortex/voxelmon/core/world/other/Mapper.java b/src/main/java/me/cortex/voxelmon/core/world/other/Mapper.java index 80fd0e99..f3729c0f 100644 --- a/src/main/java/me/cortex/voxelmon/core/world/other/Mapper.java +++ b/src/main/java/me/cortex/voxelmon/core/world/other/Mapper.java @@ -181,6 +181,11 @@ public class Mapper { return (Byte.toUnsignedLong(light)<<56)|(Integer.toUnsignedLong(bentry.id) << 47)|(Integer.toUnsignedLong(sentry.id)<<27); } + public BlockState getBlockStateFromId(long id) { + int blockId = (int) ((id>>27)&((1<<20)-1)); + return this.blockId2stateEntry.get(blockId).state; + } + //TODO: fixme: synchronize access to this.blockId2stateEntry public StateEntry[] getStateEntries() { var set = new ArrayList<>(this.blockId2stateEntry); @@ -245,6 +250,7 @@ public class Mapper { this.storage.flush(); } + public static final class StateEntry { public final int id; public final BlockState state;