From 24e08aa11fcfe0a297a97244fc43f6f129b5785f Mon Sep 17 00:00:00 2001 From: Lukas Date: Tue, 17 Nov 2020 22:24:30 +0100 Subject: [PATCH] Load block models per version --- .../mappings/versions/VersionMapping.java | 65 +++++++++- .../minosoft/render/WorldRenderer.java | 6 +- .../render/blockModels/BlockModelLoader.java | 61 +++------- .../blockModels/subBlocks/SubBlock.java | 8 +- .../render/movement/CollisionHandler.java | 7 +- .../minosoft/render/texture/InFaceUV.java | 12 +- .../render/utility/AdditionalMath.java | 8 +- util/.idea/workspace.xml | 112 ++++++++++++++---- ...delCombinder.py => blockModelGenerator.py} | 87 +++++--------- util/version_mappings_generator.py | 4 +- 10 files changed, 226 insertions(+), 144 deletions(-) rename util/{blockModelCombinder.py => blockModelGenerator.py} (68%) diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/versions/VersionMapping.java b/src/main/java/de/bixilon/minosoft/data/mappings/versions/VersionMapping.java index eda63ebc6..2e0d6afd7 100644 --- a/src/main/java/de/bixilon/minosoft/data/mappings/versions/VersionMapping.java +++ b/src/main/java/de/bixilon/minosoft/data/mappings/versions/VersionMapping.java @@ -27,8 +27,13 @@ import de.bixilon.minosoft.data.mappings.blocks.Block; import de.bixilon.minosoft.data.mappings.blocks.Blocks; import de.bixilon.minosoft.data.mappings.particle.Particle; import de.bixilon.minosoft.data.mappings.statistics.Statistic; +import de.bixilon.minosoft.data.world.BlockPosition; import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition; -import javafx.util.Pair; +import de.bixilon.minosoft.render.blockModels.BlockModelInterface; +import de.bixilon.minosoft.render.blockModels.BlockModelLoader; +import de.bixilon.minosoft.render.blockModels.Face.FaceOrientation; +import de.bixilon.minosoft.util.Pair; +import org.apache.commons.collections.primitives.ArrayFloatList; import javax.annotation.Nullable; import java.util.HashMap; @@ -55,6 +60,8 @@ public class VersionMapping { private HashMap entityMetaIndexMap; private HashMap> entityMetaIndexOffsetParentMapping; private HashBiMap> entityIdClassMap; + private HashMap> modelMap; + private Integer blockTextureId; // OpenGL texture id for all block texture public VersionMapping(Version version) { this.version = version; @@ -276,6 +283,45 @@ public class VersionMapping { return item; } + public BlockModelInterface getBlockModel(Block block) { + if (parentMapping != null) { + BlockModelInterface blockModelInterface = parentMapping.getBlockModel(block); + if (blockModelInterface != null) { + return blockModelInterface; + } + } + BlockModelInterface model = modelMap.get(block.getMod()).get(block.getIdentifier()); + if (model == null) { + throw new NullPointerException(String.format("The block model for the following block could not be found: %s", block)); + } + return model; + } + + public boolean isBlockFull(Block block, FaceOrientation orientation) { + if (block == null || block.equals(Blocks.nullBlock)) { + return false; + } + return getBlockModel(block).full(block, orientation); + } + + public boolean isBlockFull(Block block) { + return block != null && !block.equals(Blocks.nullBlock); + } + + public ArrayFloatList prepareBlock(Block block, HashSet facesToDraw, BlockPosition position) { + return getBlockModel(block).prepare(facesToDraw, position, block); + } + + public Integer getBlockTextureId() { + if (parentMapping != null) { + Integer blockTextureId = parentMapping.getBlockTextureId(); + if (blockTextureId != null) { + return blockTextureId; + } + } + return blockTextureId; + } + public void load(Mappings type, @Nullable JsonObject data, Version version) { switch (type) { @@ -404,6 +450,21 @@ public class VersionMapping { } } } + case BLOCK_MODELS -> { + if (!version.isFlattened() && version.getVersionId() != ProtocolDefinition.PRE_FLATTENING_VERSION_ID) { + // clone all values + modelMap = Versions.PRE_FLATTENING_MAPPING.modelMap; + break; + } + + if (data == null) { + modelMap = new HashMap<>(); + break; + } + Pair>, Integer> pair = BlockModelLoader.load(data); + modelMap = pair.key; + blockTextureId = pair.value; + } } loaded.add(type); } @@ -428,7 +489,7 @@ public class VersionMapping { loadEntityMapping(mod, parent, fullModData); } - metaDataIndexOffset += entityMetaIndexOffsetParentMapping.get(parent).getValue(); + metaDataIndexOffset += entityMetaIndexOffsetParentMapping.get(parent).value; } // meta data index if (data.has("data")) { diff --git a/src/main/java/de/bixilon/minosoft/render/WorldRenderer.java b/src/main/java/de/bixilon/minosoft/render/WorldRenderer.java index 8d3d29ce5..2b19dc2d3 100644 --- a/src/main/java/de/bixilon/minosoft/render/WorldRenderer.java +++ b/src/main/java/de/bixilon/minosoft/render/WorldRenderer.java @@ -157,12 +157,12 @@ public class WorldRenderer { yield nibbleBlocks.get(new InChunkSectionLocation(location.getX(), location.getY(), location.getZ() + 1)); } }; - if (dependedBlock == null || !BlockModelLoader.getInstance().isFull(dependedBlock, FaceOrientation.inverse(orientation))) { + if (dependedBlock == null || !connection.getMapping().isBlockFull(dependedBlock, FaceOrientation.inverse(orientation))) { facesToDraw.add(orientation); } } if (!facesToDraw.isEmpty()) { - nibbleMap.addAll(BlockModelLoader.getInstance().prepare(block, facesToDraw, new BlockPosition(chunkLocation, sectionHeight, location))); + nibbleMap.addAll(connection.getMapping().prepareBlock(block, facesToDraw, new BlockPosition(chunkLocation, sectionHeight, location))); } }); return nibbleMap; @@ -171,7 +171,7 @@ public class WorldRenderer { public void draw() { glPushMatrix(); - glBindTexture(GL_TEXTURE_2D, BlockModelLoader.getInstance().getTextureLoader().getTextureID()); + glBindTexture(GL_TEXTURE_2D, connection.getMapping().getBlockTextureId()); glBegin(GL_QUADS); for (ConcurrentHashMap chunk : faces.values()) { for (ArrayFloatList nibble : chunk.values()) { diff --git a/src/main/java/de/bixilon/minosoft/render/blockModels/BlockModelLoader.java b/src/main/java/de/bixilon/minosoft/render/blockModels/BlockModelLoader.java index f9eb529b9..217f23332 100644 --- a/src/main/java/de/bixilon/minosoft/render/blockModels/BlockModelLoader.java +++ b/src/main/java/de/bixilon/minosoft/render/blockModels/BlockModelLoader.java @@ -22,6 +22,7 @@ import de.bixilon.minosoft.data.world.BlockPosition; import de.bixilon.minosoft.render.blockModels.Face.FaceOrientation; import de.bixilon.minosoft.render.blockModels.subBlocks.SubBlock; import de.bixilon.minosoft.render.texture.TextureLoader; +import de.bixilon.minosoft.util.Pair; import de.bixilon.minosoft.util.Util; import org.apache.commons.collections.primitives.ArrayFloatList; @@ -31,11 +32,13 @@ import java.util.HashSet; import java.util.Map; public class BlockModelLoader { - private final TextureLoader textureLoader; - private final HashMap> modelMap; - - public BlockModelLoader(JsonObject data) { - modelMap = new HashMap<>(); + /** + * + * @param data json file which describes all block models + * @return blockModels, textureID + */ + public static Pair>, Integer> load(JsonObject data) { + HashMap> modelMap = new HashMap<>(); HashSet mods = new HashSet<>(); mods.add(data); HashMap tints = null; @@ -52,14 +55,15 @@ public class BlockModelLoader { } blockModels.put(modName, loadModels(mod)); } - textureLoader = new TextureLoader(getTextures(blockModels), tints); - applyTextures(blockModels); + TextureLoader textureLoader = new TextureLoader(getTextures(blockModels), tints); + applyTextures(modelMap, blockModels, textureLoader); for (JsonObject mod : mods) { - loadBlocks(mod, blockModels.get(mod.get("mod").getAsString())); + loadBlocks(modelMap, mod, blockModels.get(mod.get("mod").getAsString())); } + return new Pair<>(modelMap, textureLoader.getTextureID()); } - private void loadBlocks(JsonObject mod, HashMap> blockModels) { + private static void loadBlocks(HashMap> modelMap, JsonObject mod, HashMap> blockModels) { for (Map.Entry blockEntry : mod.get("blockStates").getAsJsonObject().entrySet()) { JsonObject block = blockEntry.getValue().getAsJsonObject(); if (block.has("states")) { @@ -71,7 +75,7 @@ public class BlockModelLoader { } } - private HashMap> loadModels(JsonObject mod) { + private static HashMap> loadModels(JsonObject mod) { HashMap> modMap = new HashMap<>(); for (Map.Entry block : mod.getAsJsonObject("blockModels").entrySet()) { modMap.put(block.getKey(), BlockModelInterface.load(block.getValue().getAsJsonObject(), mod.getAsJsonObject("blockModels"))); @@ -79,7 +83,7 @@ public class BlockModelLoader { return modMap; } - public HashMap> getTextures(HashMap>> blockModels) { + public static HashMap> getTextures(HashMap>> blockModels) { HashMap> textures = new HashMap<>(); for (Map.Entry>> mod : blockModels.entrySet()) { HashSet modTextures = new HashSet<>(); @@ -93,7 +97,7 @@ public class BlockModelLoader { return textures; } - public void applyTextures(HashMap>> blockModels) { + public static void applyTextures(HashMap> modelMap, HashMap>> blockModels, TextureLoader textureLoader) { for (Map.Entry>> mod : blockModels.entrySet()) { for (Map.Entry> block : mod.getValue().entrySet()) { for (SubBlock subBlock : block.getValue()) { @@ -103,7 +107,7 @@ public class BlockModelLoader { } } - private HashMap readTints(JsonObject json) { + private static HashMap readTints(JsonObject json) { HashMap result = new HashMap<>(); if (json.has("tinted_textures")) { JsonObject textures = json.get("tinted_textures").getAsJsonObject(); @@ -118,35 +122,4 @@ public class BlockModelLoader { } return result; } - - public BlockModelInterface getBlockModel(Block block) { - BlockModelInterface model = modelMap.get(block.getMod()).get(block.getIdentifier()); - if (model == null) { - throw new RuntimeException(String.format("Block model for could not be found: %s", block)); - } - return model; - } - - public boolean isFull(Block block, FaceOrientation orientation) { - if (block == null || block.equals(Blocks.nullBlock)) { - return false; - } - return getBlockModel(block).full(block, orientation); - } - - public boolean isFull(Block block) { - return block != null && !block.equals(Blocks.nullBlock); - } - - public ArrayFloatList prepare(Block block, HashSet facesToDraw, BlockPosition position) { - return getBlockModel(block).prepare(facesToDraw, position, block); - } - - public TextureLoader getTextureLoader() { - return textureLoader; - } - - public void clear() { - modelMap.clear(); - } } diff --git a/src/main/java/de/bixilon/minosoft/render/blockModels/subBlocks/SubBlock.java b/src/main/java/de/bixilon/minosoft/render/blockModels/subBlocks/SubBlock.java index 5370bac8e..3a0a61b9a 100644 --- a/src/main/java/de/bixilon/minosoft/render/blockModels/subBlocks/SubBlock.java +++ b/src/main/java/de/bixilon/minosoft/render/blockModels/subBlocks/SubBlock.java @@ -26,7 +26,6 @@ import java.util.HashSet; import java.util.Map; public class SubBlock { - private final HashMap textureCoordinates; private HashMap textures; private final HashMap textureRotations; private final boolean[] full; @@ -38,7 +37,6 @@ public class SubBlock { uv = new HashMap<>(); textures = new HashMap<>(); textureRotations = new HashMap<>(); - textureCoordinates = new HashMap<>(); SubBlockPosition from = new SubBlockPosition(json.getAsJsonArray("from")); SubBlockPosition to = new SubBlockPosition(json.getAsJsonArray("to")); @@ -57,7 +55,6 @@ public class SubBlock { } public SubBlock(SubBlock subBlock) { - textureCoordinates = subBlock.textureCoordinates; textureRotations = subBlock.textureRotations; uv = subBlock.uv; cuboid = new Cuboid(subBlock.cuboid); @@ -94,7 +91,7 @@ public class SubBlock { if (texture == -1) { continue; } - textureCoordinates.put(entry.getKey(), texture); + uv.get(entry.getKey()).prepare(texture, loader); } // clean up textures.clear(); @@ -132,13 +129,12 @@ public class SubBlock { } private ArrayFloatList prepareFace(FaceOrientation faceDirection, BlockPosition position) { - if (!textureCoordinates.containsKey(faceDirection)) { + if (! uv.get(faceDirection).exists()) { return null; } ArrayFloatList result = new ArrayFloatList(); SubBlockPosition[] positions = cuboid.getFacePositions(faceDirection); InFaceUV inFaceUV = uv.get(faceDirection); - inFaceUV.prepare(textureCoordinates.get(faceDirection)); int rotation = textureRotations.get(faceDirection); for (int i = 0; i < positions.length; i++) { result.addAll(inFaceUV.getFloats(i + rotation)); diff --git a/src/main/java/de/bixilon/minosoft/render/movement/CollisionHandler.java b/src/main/java/de/bixilon/minosoft/render/movement/CollisionHandler.java index 705967a35..ba8324344 100644 --- a/src/main/java/de/bixilon/minosoft/render/movement/CollisionHandler.java +++ b/src/main/java/de/bixilon/minosoft/render/movement/CollisionHandler.java @@ -13,6 +13,7 @@ package de.bixilon.minosoft.render.movement; +import de.bixilon.minosoft.data.mappings.versions.VersionMapping; import de.bixilon.minosoft.data.world.BlockPosition; import de.bixilon.minosoft.data.world.World; import de.bixilon.minosoft.protocol.network.Connection; @@ -23,10 +24,12 @@ import de.bixilon.minosoft.render.utility.Vec3; public class CollisionHandler { private final World world; private final PlayerController controller; + private final VersionMapping versionMapping; public CollisionHandler(Connection connection) { world = connection.getPlayer().getWorld(); this.controller = connection.getRenderProperties().getController(); + this.versionMapping = connection.getMapping(); } public void handleCollisions() { @@ -90,16 +93,14 @@ public class CollisionHandler { float width = controller.getPlayerWidth(); int[] xPositions = AdditionalMath.valuesBetween(AdditionalMath.betterRound(testPosition.x + width), AdditionalMath.betterRound(testPosition.x - width)); - int[] yPositions = AdditionalMath.valuesBetween(AdditionalMath.betterRound(testPosition.y), AdditionalMath.betterRound(testPosition.y + controller.getPlayerHeight())); - int[] zPositions = AdditionalMath.valuesBetween(AdditionalMath.betterRound(testPosition.z + width), AdditionalMath.betterRound(testPosition.z - width)); for (int xPos : xPositions) { for (int yPos : yPositions) { for (int zPos : zPositions) { BlockPosition pos = new BlockPosition(xPos, (short) yPos, zPos); - if (BlockModelLoader.getInstance().isFull(world.getBlock(pos))) { + if (versionMapping.isBlockFull(world.getBlock(pos))) { return false; } } diff --git a/src/main/java/de/bixilon/minosoft/render/texture/InFaceUV.java b/src/main/java/de/bixilon/minosoft/render/texture/InFaceUV.java index a8bc65f7a..3c2d3084a 100644 --- a/src/main/java/de/bixilon/minosoft/render/texture/InFaceUV.java +++ b/src/main/java/de/bixilon/minosoft/render/texture/InFaceUV.java @@ -21,7 +21,7 @@ import org.apache.commons.collections.primitives.ArrayFloatList; public class InFaceUV { public final int u1, v1, u2, v2; - public float realU1, realV1, realU2, realV2; + public float realU1 = -1, realV1, realU2, realV2; public InFaceUV(JsonArray json) { u1 = json.get(0).getAsInt(); @@ -35,9 +35,9 @@ public class InFaceUV { u2 = v2 = 16; } - public void prepare(float texture) { - realU1 = texture + u1 * BlockModelLoader.getInstance().getTextureLoader().getStep() / RenderConstants.TEXTURE_PACK_RESOLUTION; - realU2 = texture + u2 * BlockModelLoader.getInstance().getTextureLoader().getStep() / RenderConstants.TEXTURE_PACK_RESOLUTION; + public void prepare(float texture, TextureLoader textureLoader) { + realU1 = texture + u1 * textureLoader.getStep() / RenderConstants.TEXTURE_PACK_RESOLUTION; + realU2 = texture + u2 * textureLoader.getStep() / RenderConstants.TEXTURE_PACK_RESOLUTION; realV1 = (float) v1 / RenderConstants.TEXTURE_PACK_RESOLUTION; realV2 = (float) v2 / RenderConstants.TEXTURE_PACK_RESOLUTION; } @@ -71,4 +71,8 @@ public class InFaceUV { } return result; } + + public boolean exists() { + return realU1 == -1; + } } diff --git a/src/main/java/de/bixilon/minosoft/render/utility/AdditionalMath.java b/src/main/java/de/bixilon/minosoft/render/utility/AdditionalMath.java index 9ca5e6493..48422bbf2 100644 --- a/src/main/java/de/bixilon/minosoft/render/utility/AdditionalMath.java +++ b/src/main/java/de/bixilon/minosoft/render/utility/AdditionalMath.java @@ -32,10 +32,10 @@ public class AdditionalMath { return result; } - public static int betterRound(double x) { - if (x >= 0) { - return (int) x; + public static int betterRound(double value) { + if (value >= 0) { + return (int) value; } - return (int) x - 1; + return (int) value - 1; } } diff --git a/util/.idea/workspace.xml b/util/.idea/workspace.xml index f7047dc48..4a8f58476 100644 --- a/util/.idea/workspace.xml +++ b/util/.idea/workspace.xml @@ -2,13 +2,16 @@ - - - - - - - + + + + + + + + + + + @@ -52,7 +56,7 @@ - + + + + + - + + + + @@ -107,6 +136,17 @@ + + + @@ -116,28 +156,60 @@ - - + + + - - + + + - - + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + file://$PROJECT_DIR$/version_mappings_generator.py + 281 + + +