WIP
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
package me.cortex.voxelmon.core.rendering;
|
||||||
|
|
||||||
|
//Manages the storage and updating of model states, textures and colours
|
||||||
|
public class ModelManager {
|
||||||
|
}
|
||||||
@@ -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() {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -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;
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user