This commit is contained in:
mcrcortex
2024-01-16 11:16:29 +10:00
parent 02daa85097
commit 57c0e7daf7
6 changed files with 113 additions and 101 deletions

View File

@@ -0,0 +1,5 @@
package me.cortex.voxelmon.core.rendering;
//Manages the storage and updating of model states, textures and colours
public class ModelManager {
}

View File

@@ -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() {
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -6,6 +6,7 @@ import me.cortex.voxelmon.core.util.Mesher2D;
import me.cortex.voxelmon.core.world.WorldEngine; import me.cortex.voxelmon.core.world.WorldEngine;
import me.cortex.voxelmon.core.world.WorldSection; import me.cortex.voxelmon.core.world.WorldSection;
import me.cortex.voxelmon.core.world.other.Mapper; import me.cortex.voxelmon.core.world.other.Mapper;
import net.minecraft.client.MinecraftClient;
import net.minecraft.util.math.Direction; import net.minecraft.util.math.Direction;
import org.lwjgl.system.MemoryUtil; import org.lwjgl.system.MemoryUtil;
@@ -16,9 +17,11 @@ public class RenderDataFactory {
private final WorldEngine world; private final WorldEngine world;
private final long[] sectionCache = new long[32*32*32]; private final long[] sectionCache = new long[32*32*32];
private final long[] connectedSectionCache = 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) { public RenderDataFactory(WorldEngine world) {
this.world = 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 //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)) // its neigbor or not (0 if it does 1 if it doesnt (0 is default behavior))
public BuiltSectionGeometry generateMesh(WorldSection section, int buildMask) { 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: 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 //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(); var array = this.mesher.getArray();
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
var quad = array[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; connectedData = null;
@@ -130,7 +134,7 @@ public class RenderDataFactory {
var array = this.mesher.getArray(); var array = this.mesher.getArray();
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
var quad = array[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; connectedData = null;
@@ -175,7 +179,7 @@ public class RenderDataFactory {
var array = this.mesher.getArray(); var array = this.mesher.getArray();
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
var quad = array[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; connectedData = null;
@@ -220,7 +224,7 @@ public class RenderDataFactory {
var array = this.mesher.getArray(); var array = this.mesher.getArray();
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
var quad = array[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; connectedData = null;
@@ -265,7 +269,7 @@ public class RenderDataFactory {
var array = this.mesher.getArray(); var array = this.mesher.getArray();
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
var quad = array[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; connectedData = null;
@@ -310,7 +314,7 @@ public class RenderDataFactory {
var array = this.mesher.getArray(); var array = this.mesher.getArray();
for (int i = 0; i < count; i++) { for (int i = 0; i < count; i++) {
var quad = array[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; connectedData = null;

View File

@@ -181,6 +181,11 @@ public class Mapper {
return (Byte.toUnsignedLong(light)<<56)|(Integer.toUnsignedLong(bentry.id) << 47)|(Integer.toUnsignedLong(sentry.id)<<27); 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 //TODO: fixme: synchronize access to this.blockId2stateEntry
public StateEntry[] getStateEntries() { public StateEntry[] getStateEntries() {
var set = new ArrayList<>(this.blockId2stateEntry); var set = new ArrayList<>(this.blockId2stateEntry);
@@ -245,6 +250,7 @@ public class Mapper {
this.storage.flush(); this.storage.flush();
} }
public static final class StateEntry { public static final class StateEntry {
public final int id; public final int id;
public final BlockState state; public final BlockState state;