From 596866c3ee0a86da4a79aba69e65d0d8a5d2e28e Mon Sep 17 00:00:00 2001 From: Bixilon Date: Thu, 4 Nov 2021 16:27:29 +0100 Subject: [PATCH] model loading --- .../data/assets/MinecraftAssetsManager.kt | 2 +- .../minosoft/data/direction/Directions.kt | 52 +----- .../bixilon/minosoft/data/registries/AABB.kt | 2 +- .../registries/registry/Registry.kt | 2 +- ...onMeshCollection.kt => SectionPreparer.kt} | 22 ++- .../gui/rendering/block/WorldRenderer.kt | 43 ++++- ...ectionArrayMesh.kt => ChunkSectionMesh.kt} | 2 +- .../block/mesh/ChunkSectionMeshes.kt | 32 ++++ .../gui/rendering/block/models/BlockModel.kt | 66 -------- .../block/models/BlockModelElement.kt | 102 ------------ .../rendering/block/models/BlockModelFace.kt | 156 ------------------ .../gui/rendering/models/GUILights.kt | 29 ++++ .../gui/rendering/models/ModelLoader.kt | 105 ++++++++++++ .../rendering/models/builtin/BuiltinModels.kt | 24 +++ .../models/builtin/UnbakedBlockEntityModel.kt | 25 +++ .../models/builtin/UnbakedGeneratedModel.kt | 25 +++ .../rendering/models/display/ModelDisplay.kt | 37 +++++ .../models/display/ModelDisplayPositions.kt | 39 +++++ .../FaceSize.kt => models/unbaked/Model.kt} | 9 +- .../models/unbaked/UnbakedBlockModel.kt | 23 +++ .../models/unbaked/UnbakedItemModel.kt | 25 +++ .../rendering/models/unbaked/UnbakedModel.kt | 68 ++++++++ .../models/unbaked/element/UnbakedElement.kt | 51 ++++++ .../unbaked/element/UnbakedElementFace.kt | 47 ++++++ .../unbaked/element/UnbakedElementRotation.kt | 40 +++++ .../minosoft/gui/rendering/util/VecUtil.kt | 22 --- .../gui/rendering/util/vec/Vec2Util.kt | 2 +- .../gui/rendering/util/vec/vec3/Vec3Util.kt | 39 +++++ .../gui/rendering/util/vec/vec3/Vec3iUtil.kt | 40 +++++ .../bixilon/minosoft/util/ShutdownManager.kt | 4 +- .../java/de/bixilon/minosoft/util/Util.java | 7 +- .../bixilon/minosoft/util/enum/ValuesEnum.kt | 2 +- 32 files changed, 727 insertions(+), 417 deletions(-) rename src/main/java/de/bixilon/minosoft/gui/rendering/block/{mesh/ChunkSectionMeshCollection.kt => SectionPreparer.kt} (65%) rename src/main/java/de/bixilon/minosoft/gui/rendering/block/mesh/{ChunkSectionArrayMesh.kt => ChunkSectionMesh.kt} (94%) create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/block/mesh/ChunkSectionMeshes.kt delete mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/block/models/BlockModel.kt delete mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/block/models/BlockModelElement.kt delete mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/block/models/BlockModelFace.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/models/GUILights.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/models/ModelLoader.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/models/builtin/BuiltinModels.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/models/builtin/UnbakedBlockEntityModel.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/models/builtin/UnbakedGeneratedModel.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/models/display/ModelDisplay.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/models/display/ModelDisplayPositions.kt rename src/main/java/de/bixilon/minosoft/gui/rendering/{block/models/FaceSize.kt => models/unbaked/Model.kt} (76%) create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/UnbakedBlockModel.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/UnbakedItemModel.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/UnbakedModel.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/element/UnbakedElement.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/element/UnbakedElementFace.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/element/UnbakedElementRotation.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/util/vec/vec3/Vec3Util.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/util/vec/vec3/Vec3iUtil.kt diff --git a/src/main/java/de/bixilon/minosoft/data/assets/MinecraftAssetsManager.kt b/src/main/java/de/bixilon/minosoft/data/assets/MinecraftAssetsManager.kt index ac868820f..9951df522 100644 --- a/src/main/java/de/bixilon/minosoft/data/assets/MinecraftAssetsManager.kt +++ b/src/main/java/de/bixilon/minosoft/data/assets/MinecraftAssetsManager.kt @@ -164,7 +164,7 @@ class MinecraftAssetsManager( } private fun parseAssetsIndex(hash: String): Map { - return parseAssetsIndex(Util.readJsonFromStream(readAssetAsStream(hash))) + return parseAssetsIndex(Util.readJsonFromStream(readAssetAsStream(hash), true)) } private fun parseAssetsIndex(json: JsonObject): Map { diff --git a/src/main/java/de/bixilon/minosoft/data/direction/Directions.kt b/src/main/java/de/bixilon/minosoft/data/direction/Directions.kt index 1be982d46..e656fe01b 100644 --- a/src/main/java/de/bixilon/minosoft/data/direction/Directions.kt +++ b/src/main/java/de/bixilon/minosoft/data/direction/Directions.kt @@ -14,12 +14,9 @@ package de.bixilon.minosoft.data.direction import de.bixilon.minosoft.data.Axes import de.bixilon.minosoft.data.registries.blocks.properties.serializer.BlockPropertiesSerializer -import de.bixilon.minosoft.gui.rendering.block.models.BlockModelElement -import de.bixilon.minosoft.gui.rendering.block.models.FaceSize import de.bixilon.minosoft.gui.rendering.util.VecUtil.get import de.bixilon.minosoft.util.KUtil import de.bixilon.minosoft.util.enum.ValuesEnum -import glm_.vec2.Vec2i import glm_.vec3.Vec3 import glm_.vec3.Vec3d import glm_.vec3.Vec3i @@ -53,48 +50,6 @@ enum class Directions( } } - fun sidesNextTo(direction: Directions): Set { - return when (direction) { - NORTH, SOUTH -> setOf(EAST, WEST) - EAST, WEST -> setOf(NORTH, SOUTH) - else -> emptySet() - } - } - - /** - * @return the size of the face in this direction. null if the face is not touching the border (determinated by the block resolution) - */ - fun getFaceBorderSizes(start: Vec3, end: Vec3): FaceSize? { - // check if face is touching the border of a block - - if (!isBlockResolutionBorder(start, end)) { - return null - } - return getFaceSize(start, end) - } - - fun getFaceSize(start: Vec3, end: Vec3): FaceSize { - return when (this) { - DOWN, UP -> FaceSize(Vec2i(start.x, start.z), Vec2i(end.x, end.z)) - NORTH, SOUTH -> FaceSize(Vec2i(start.x, start.y), Vec2i(end.x, end.y)) - EAST, WEST -> FaceSize(Vec2i(start.y, start.z), Vec2i(end.y, end.z)) - } - } - - private fun isBlockResolutionBorder(start: Vec3, end: Vec3): Boolean { - return isCoordinateBorder(vector.x, start.x, end.x) || isCoordinateBorder(vector.y, start.y, end.y) || isCoordinateBorder(vector.z, start.z, end.z) - } - - private fun isCoordinateBorder(directionValue: Int, start: Float, end: Float): Boolean { - if (directionValue == 1) { - return start == BlockModelElement.BLOCK_RESOLUTION_FLOAT || end == BlockModelElement.BLOCK_RESOLUTION_FLOAT - } - if (directionValue == -1) { - return start == 0.0f || end == 0.0f - } - return false - } - operator fun get(axis: Axes): Int { return vector[axis] } @@ -121,6 +76,13 @@ enum class Directions( return NAME_MAP[value] ?: throw IllegalArgumentException("No such property: $value") } + override fun get(name: String): Directions { + if (name.lowercase() == "bottom") { + return DOWN + } + return super.get(name) + } + @JvmStatic fun byId(id: Int): Directions { return VALUES[id] diff --git a/src/main/java/de/bixilon/minosoft/data/registries/AABB.kt b/src/main/java/de/bixilon/minosoft/data/registries/AABB.kt index c6cbe3894..b7bdb0d5a 100644 --- a/src/main/java/de/bixilon/minosoft/data/registries/AABB.kt +++ b/src/main/java/de/bixilon/minosoft/data/registries/AABB.kt @@ -19,7 +19,7 @@ import de.bixilon.minosoft.data.direction.Directions import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY import de.bixilon.minosoft.gui.rendering.util.VecUtil.ONE import de.bixilon.minosoft.gui.rendering.util.VecUtil.get -import de.bixilon.minosoft.gui.rendering.util.VecUtil.toVec3 +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.toVec3 import de.bixilon.minosoft.util.MMath.ceil import de.bixilon.minosoft.util.MMath.floor import glm_.Java.Companion.glm diff --git a/src/main/java/de/bixilon/minosoft/data/registries/registries/registry/Registry.kt b/src/main/java/de/bixilon/minosoft/data/registries/registries/registry/Registry.kt index 0a25e43c0..b38988b5d 100644 --- a/src/main/java/de/bixilon/minosoft/data/registries/registries/registry/Registry.kt +++ b/src/main/java/de/bixilon/minosoft/data/registries/registries/registry/Registry.kt @@ -94,7 +94,7 @@ open class Registry( } open operator fun get(resourceLocation: String): T? { - return get(ResourceLocation.getPathResourceLocation(resourceLocation)) + return get(resourceLocation.toResourceLocation()) } open operator fun get(resourceLocation: ResourceLocationAble): T? { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/block/mesh/ChunkSectionMeshCollection.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/block/SectionPreparer.kt similarity index 65% rename from src/main/java/de/bixilon/minosoft/gui/rendering/block/mesh/ChunkSectionMeshCollection.kt rename to src/main/java/de/bixilon/minosoft/gui/rendering/block/SectionPreparer.kt index 69e5ab11c..1e54d9d73 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/block/mesh/ChunkSectionMeshCollection.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/block/SectionPreparer.kt @@ -11,16 +11,22 @@ * This software is not affiliated with Mojang AB, the original developer of Minecraft. */ -package de.bixilon.minosoft.gui.rendering.block.mesh +package de.bixilon.minosoft.gui.rendering.block +import de.bixilon.minosoft.data.world.ChunkSection import de.bixilon.minosoft.gui.rendering.RenderWindow +import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMesh -class ChunkSectionMeshCollection( - renderWindow: RenderWindow, - val opaqueMesh: ChunkSectionArrayMesh = ChunkSectionArrayMesh(renderWindow), - var translucentMesh: ChunkSectionArrayMesh? = ChunkSectionArrayMesh(renderWindow), - var transparentMesh: ChunkSectionArrayMesh? = ChunkSectionArrayMesh(renderWindow), +class SectionPreparer( + val renderWindow: RenderWindow, ) { - var lowestBlockHeight = 0 - var highestBlockHeight = 0 + + + fun prepare(section: ChunkSection): ChunkSectionMesh { + val mesh = ChunkSectionMesh(renderWindow) + + + + return mesh + } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/block/WorldRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/block/WorldRenderer.kt index bbf5bdd3e..5f2e38519 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/block/WorldRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/block/WorldRenderer.kt @@ -13,24 +13,65 @@ package de.bixilon.minosoft.gui.rendering.block +import de.bixilon.minosoft.data.assets.AssetsUtil +import de.bixilon.minosoft.data.assets.Resources import de.bixilon.minosoft.data.direction.Directions import de.bixilon.minosoft.data.direction.FakeDirection import de.bixilon.minosoft.data.registries.ResourceLocation +import de.bixilon.minosoft.data.world.ChunkSection import de.bixilon.minosoft.data.world.World import de.bixilon.minosoft.gui.rendering.RenderWindow import de.bixilon.minosoft.gui.rendering.Renderer import de.bixilon.minosoft.gui.rendering.RendererBuilder +import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMesh +import de.bixilon.minosoft.gui.rendering.models.ModelLoader import de.bixilon.minosoft.gui.rendering.system.base.RenderSystem +import de.bixilon.minosoft.gui.rendering.system.base.phases.OpaqueDrawable import de.bixilon.minosoft.gui.rendering.util.VecUtil.plus import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection +import de.bixilon.minosoft.util.KUtil.toResourceLocation import glm_.vec2.Vec2i +import java.io.FileInputStream +import java.util.zip.GZIPInputStream +import java.util.zip.ZipInputStream class WorldRenderer( private val connection: PlayConnection, override val renderWindow: RenderWindow, -) : Renderer { +) : Renderer, OpaqueDrawable { override val renderSystem: RenderSystem = renderWindow.renderSystem + private val shader = renderSystem.createShader("minosoft:world".toResourceLocation()) private val world: World = connection.world + private val sectionPreparer = SectionPreparer(renderWindow) + private lateinit var mesh: ChunkSectionMesh + + + override fun init() { + val asset = Resources.getAssetVersionByVersion(connection.version) + val zip = ZipInputStream(GZIPInputStream(FileInputStream(AssetsUtil.getAssetDiskPath(asset.clientJarHash!!, true)))) + val modelLoader = ModelLoader(zip) + modelLoader.load() + + val dirt = connection.registries.blockRegistry["dirt"]?.defaultState + val chunk = ChunkSection(Array(4096) { dirt }) + mesh = sectionPreparer.prepare(chunk) + mesh.load() + } + + override fun postInit() { + shader.load() + renderWindow.textureManager.staticTextures.use(shader) + renderWindow.textureManager.staticTextures.animator.use(shader) + } + + override fun setupOpaque() { + super.setupOpaque() + shader.use() + } + + override fun drawOpaque() { + mesh.draw() + } companion object : RendererBuilder { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/block/mesh/ChunkSectionArrayMesh.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/block/mesh/ChunkSectionMesh.kt similarity index 94% rename from src/main/java/de/bixilon/minosoft/gui/rendering/block/mesh/ChunkSectionArrayMesh.kt rename to src/main/java/de/bixilon/minosoft/gui/rendering/block/mesh/ChunkSectionMesh.kt index c5af3cc5c..63d98e90c 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/block/mesh/ChunkSectionArrayMesh.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/block/mesh/ChunkSectionMesh.kt @@ -23,7 +23,7 @@ import de.bixilon.minosoft.gui.rendering.util.mesh.MeshStruct import glm_.vec2.Vec2 import glm_.vec3.Vec3 -class ChunkSectionArrayMesh(renderWindow: RenderWindow) : Mesh(renderWindow, SectionArrayMeshStruct, initialCacheSize = 100000) { +class ChunkSectionMesh(renderWindow: RenderWindow) : Mesh(renderWindow, SectionArrayMeshStruct, initialCacheSize = 100000) { fun addVertex(position: Vec3, uv: Vec2, texture: AbstractTexture, tintColor: RGBColor?, light: Int) { val color = tintColor ?: ChatColors.WHITE diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/block/mesh/ChunkSectionMeshes.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/block/mesh/ChunkSectionMeshes.kt new file mode 100644 index 000000000..9246e1a9c --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/block/mesh/ChunkSectionMeshes.kt @@ -0,0 +1,32 @@ +/* + * Minosoft + * Copyright (C) 2021 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.block.mesh + +import de.bixilon.minosoft.data.registries.AABB +import de.bixilon.minosoft.gui.rendering.RenderWindow +import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY +import glm_.vec3.Vec3i + +class ChunkSectionMeshes( + renderWindow: RenderWindow, + val opaqueMesh: ChunkSectionMesh = ChunkSectionMesh(renderWindow), + var translucentMesh: ChunkSectionMesh? = ChunkSectionMesh(renderWindow), + var transparentMesh: ChunkSectionMesh? = ChunkSectionMesh(renderWindow), +) { + val minPosition = Vec3i.EMPTY + val maxPosition = Vec3i.EMPTY + + lateinit var aabb: AABB + private set +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/block/models/BlockModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/block/models/BlockModel.kt deleted file mode 100644 index 5fc7085de..000000000 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/block/models/BlockModel.kt +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Minosoft - * Copyright (C) 2021 Moritz Zwerger - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. If not, see . - * - * This software is not affiliated with Mojang AB, the original developer of Minecraft. - */ - -package de.bixilon.minosoft.gui.rendering.block.models - -import de.bixilon.minosoft.gui.rendering.util.VecUtil.rad -import de.bixilon.minosoft.util.KUtil.listCast -import de.bixilon.minosoft.util.KUtil.nullCast -import de.bixilon.minosoft.util.KUtil.unsafeCast -import de.bixilon.minosoft.util.nbt.tag.NBTUtil.asCompound -import de.bixilon.minosoft.util.nbt.tag.NBTUtil.compoundCast -import glm_.vec3.Vec3 - -open class BlockModel( - val parent: BlockModel? = null, - data: Map, -) { - val textures: Map - val elements: List - val rotation: Vec3 = Vec3(data["x"]?.unsafeCast() ?: parent?.rotation?.x ?: 0.0f, data["y"]?.unsafeCast() ?: parent?.rotation?.y ?: 0.0f, data["z"]?.unsafeCast() ?: parent?.rotation?.z ?: 0.0f).rad - val uvLock: Boolean = data["uvlock"].nullCast() ?: parent?.uvLock ?: false - val rescale: Boolean = data["rescale"].nullCast() ?: parent?.rescale ?: false - val ambientOcclusion: Boolean = data["ambientocclusion"].nullCast() ?: parent?.ambientOcclusion ?: true - - init { - textures = data["textures"]?.compoundCast()?.let { - val textures: MutableMap = parent?.textures?.toMutableMap() ?: mutableMapOf() - for ((type, value) in it) { - textures[type] = value.unsafeCast() - } - for ((type, texture) in textures) { - textures[type] = getTextureByType(textures, texture) - } - textures.toMap() - } ?: parent?.textures ?: mapOf() - - - elements = data["elements"]?.listCast()?.let { - val elements: MutableList = mutableListOf() - for (element in it) { - elements += BlockModelElement(element.asCompound()) - } - elements.toList() - } ?: parent?.elements ?: listOf() - } - - private fun getTextureByType(textures: Map, type: String): String { - var currentValue: String = type - while (currentValue.startsWith("#")) { - textures[currentValue.removePrefix("#")].let { - currentValue = it ?: return currentValue - } - } - return currentValue - } -} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/block/models/BlockModelElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/block/models/BlockModelElement.kt deleted file mode 100644 index 688a56967..000000000 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/block/models/BlockModelElement.kt +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Minosoft - * Copyright (C) 2021 Moritz Zwerger - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. If not, see . - * - * This software is not affiliated with Mojang AB, the original developer of Minecraft. - */ - -package de.bixilon.minosoft.gui.rendering.block.models - -import de.bixilon.minosoft.data.Axes -import de.bixilon.minosoft.data.direction.Directions -import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY -import de.bixilon.minosoft.gui.rendering.util.VecUtil.rotate -import de.bixilon.minosoft.gui.rendering.util.VecUtil.toVec3 -import de.bixilon.minosoft.util.KUtil.nullCast -import de.bixilon.minosoft.util.KUtil.unsafeCast -import de.bixilon.minosoft.util.nbt.tag.NBTUtil.asCompound -import de.bixilon.minosoft.util.nbt.tag.NBTUtil.compoundCast -import glm_.func.rad -import glm_.vec3.Vec3 - -open class BlockModelElement( - data: Map, -) { - val from: Vec3 = data["from"]?.toVec3() ?: Vec3.EMPTY - val to: Vec3 = data["to"]?.toVec3() ?: Vec3(BLOCK_RESOLUTION) - val shade: Boolean = data["shade"].nullCast() ?: true - val faces: MutableMap = mutableMapOf() - val transformedPositions: Array = arrayOf( - Vec3(from.x, from.y, from.z), - Vec3(to.x, from.y, from.z), - Vec3(from.x, from.y, to.z), - Vec3(to.x, from.y, to.z), - Vec3(from.x, to.y, from.z), - Vec3(to.x, to.y, from.z), - Vec3(from.x, to.y, to.z), - Vec3(to.x, to.y, to.z), - ) - - init { - - data["rotation"]?.compoundCast()?.let { - val axis = Axes[it["axis"].unsafeCast()] - val angle = it["angle"].unsafeCast().toFloat().rad - val rescale = it["rescale"].nullCast() ?: false - rotatePositions(transformedPositions, axis, angle, it["origin"]!!.toVec3(), rescale) - } - - data["faces"]?.compoundCast()?.let { - for ((directionName, json) in it) { - val direction = Directions[directionName] - faces[direction] = BlockModelFace(json.asCompound(), from, to, direction) - } - } - - // transformed positions - for ((index, position) in transformedPositions.withIndex()) { - transformedPositions[index] = transformPosition(position) - } - } - - companion object { - const val BLOCK_RESOLUTION = 16 - const val BLOCK_RESOLUTION_FLOAT = BLOCK_RESOLUTION.toFloat() - - val FACE_POSITION_MAP_TEMPLATE = arrayOf( - intArrayOf(0, 2, 3, 1), - intArrayOf(6, 4, 5, 7), - intArrayOf(1, 5, 4, 0), - intArrayOf(2, 6, 7, 3), - intArrayOf(6, 2, 0, 4), - intArrayOf(5, 1, 3, 7) - ) - - fun rotatePositions(positions: Array, axis: Axes, angle: Float, origin: Vec3, rescale: Boolean) { - // TODO: optimize for 90deg, 180deg, 270deg rotations - if (angle == 0.0f) { - return - } - for ((i, position) in positions.withIndex()) { - var transformedPosition = position - origin - transformedPosition = transformedPosition.rotate(angle, axis, rescale) - positions[i] = transformedPosition + origin - } - } - - fun transformPosition(position: Vec3): Vec3 { - - fun positionToFloat(uv: Float): Float { - return (uv - (BLOCK_RESOLUTION / 2)) / BLOCK_RESOLUTION - } - - return Vec3(positionToFloat(position.x), positionToFloat(position.y), positionToFloat(position.z)) - } - } -} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/block/models/BlockModelFace.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/block/models/BlockModelFace.kt deleted file mode 100644 index 0d7bd7008..000000000 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/block/models/BlockModelFace.kt +++ /dev/null @@ -1,156 +0,0 @@ -/* - * Minosoft - * Copyright (C) 2021 Moritz Zwerger - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. If not, see . - * - * This software is not affiliated with Mojang AB, the original developer of Minecraft. - */ - -package de.bixilon.minosoft.gui.rendering.block.models - -import de.bixilon.minosoft.data.direction.Directions -import de.bixilon.minosoft.data.registries.AABB -import de.bixilon.minosoft.gui.rendering.util.VecUtil -import de.bixilon.minosoft.gui.rendering.util.VecUtil.readUV -import de.bixilon.minosoft.util.KUtil.nullCast -import de.bixilon.minosoft.util.KUtil.toInt -import de.bixilon.minosoft.util.KUtil.unsafeCast -import glm_.func.cos -import glm_.func.sin -import glm_.vec2.Vec2 -import glm_.vec3.Vec3 -import java.util.* - -class BlockModelFace { - val textureName: String? - val cullFace: Directions? - val tint: Boolean - val positions: List - - - constructor(textureName: String?, cullFace: Directions?, tint: Boolean, positions: List) { - this.textureName = textureName - this.cullFace = cullFace - this.tint = tint - this.positions = positions - } - - constructor(data: Map, from: Vec3, to: Vec3, direction: Directions) { - tint = data.containsKey("tintindex") - textureName = data["texture"].unsafeCast().removePrefix("#") - cullFace = data["cullface"].nullCast()?.let { - if (it == "bottom") { - Directions.DOWN - } else { - Directions[it] - } - } - val positions = calculateTexturePositions(data, from, to, direction) - val rotation = data["rotation"]?.toInt()?.div(90) ?: 0 - Collections.rotate(positions, rotation) - this.positions = positions.toList() - } - - private fun calculateTexturePositions(data: Map?, from: Vec3, to: Vec3, direction: Directions): MutableList { - val (textureTopLeft: Vec2, textureBottomRight: Vec2) = data?.get("uv")?.unsafeCast>()?.readUV() ?: getTexturePositionsFromRegion(AABB(from, to), direction) - return mutableListOf( - uvToFloat(Vec2(textureTopLeft.x, textureTopLeft.y)), - uvToFloat(Vec2(textureTopLeft.x, textureBottomRight.y)), - uvToFloat(Vec2(textureBottomRight.x, textureBottomRight.y)), - uvToFloat(Vec2(textureBottomRight.x, textureTopLeft.y)), - ) - } - - private fun getTexturePositionsFromRegion(aabb: AABB, direction: Directions): Pair { - // ToDo: Remove the duplicated code in Directions - return when (direction) { - Directions.UP, Directions.DOWN -> Pair(Vec2(aabb.min.x.toInt(), aabb.max.z.toInt()), Vec2(aabb.max.x.toInt(), aabb.min.z.toInt())) - Directions.NORTH, Directions.SOUTH -> Pair(Vec2(aabb.min.x.toInt(), aabb.max.y.toInt()), Vec2(aabb.max.x.toInt(), aabb.min.y.toInt())) - Directions.EAST, Directions.WEST -> Pair(Vec2(aabb.min.z.toInt(), aabb.max.y.toInt()), Vec2(aabb.max.z.toInt(), aabb.min.y.toInt())) - } - } - - constructor(other: BlockModelFace) { - textureName = other.textureName - cullFace = other.cullFace - tint = other.tint - this.positions = other.positions - } - - constructor(vertexPositions: List, direction: Directions) { - textureName = null - cullFace = null - tint = false - val template = BlockModelElement.FACE_POSITION_MAP_TEMPLATE[direction.ordinal] - val positions: MutableList = mutableListOf() - for (templatePosition in template) { - positions += calculateTexturePosition(vertexPositions[templatePosition], direction) - } - this.positions = positions.toList() - } - - private fun calculateTexturePosition(position: Vec3, direction: Directions): Vec2 { - return when (direction) { - Directions.UP, Directions.DOWN -> Vec2(position.x, BlockModelElement.BLOCK_RESOLUTION - position.z) - Directions.NORTH, Directions.SOUTH -> Vec2(position.x, position.y) - Directions.EAST, Directions.WEST -> Vec2(position.z, BlockModelElement.BLOCK_RESOLUTION - position.y) - } - } - - fun getTexturePositionArray(direction: Directions): Array { - val template = textureTemplate[direction.ordinal] - val ret: MutableList = mutableListOf() - for (i in template.indices) { - ret += positions[template[i]] - } - return ret.toTypedArray() - } - - fun rotate(angle: Float): BlockModelFace { - if (angle == 0.0f) { - return this - } - val sin = angle.sin - val cos = angle.cos - val positions = this.positions.toMutableList() - for ((i, position) in positions.withIndex()) { - val offset = position - TEXTURE_MIDDLE - positions[i] = VecUtil.getRotatedValues(offset.x, offset.y, sin, cos, false) + TEXTURE_MIDDLE - } - return BlockModelFace(textureName, cullFace, tint, positions.toList()) - } - - fun scale(scaleFactor: Double): BlockModelFace { - val positions = positions.toMutableList() - for ((i, position) in positions.withIndex()) { - positions[i] = position * scaleFactor - } - return BlockModelFace(textureName, cullFace, tint, positions.toList()) - } - - companion object { - private fun uvToFloat(uv: Float): Float { - return (uv) / BlockModelElement.BLOCK_RESOLUTION - } - - fun uvToFloat(vec2: Vec2): Vec2 { - return Vec2(uvToFloat(vec2.x), uvToFloat(BlockModelElement.BLOCK_RESOLUTION - vec2.y)) - } - - val textureTemplate = arrayOf( - arrayOf(0, 1, 2, 3), - arrayOf(0, 1, 2, 3), - arrayOf(3, 2, 1, 0), - arrayOf(0, 1, 2, 3), - arrayOf(2, 3, 0, 1), - arrayOf(1, 0, 3, 2), - ) - - val TEXTURE_MIDDLE = Vec2(0.5, 0.5) - } -} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/GUILights.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/GUILights.kt new file mode 100644 index 000000000..fa1270e3f --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/GUILights.kt @@ -0,0 +1,29 @@ +/* + * Minosoft + * Copyright (C) 2021 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.models + +import de.bixilon.minosoft.util.KUtil +import de.bixilon.minosoft.util.enum.ValuesEnum + +enum class GUILights { + FRONT, + SIDE, + ; + + companion object : ValuesEnum { + override val VALUES: Array = values() + override val NAME_MAP: Map = KUtil.getEnumValues(VALUES) + + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/ModelLoader.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/ModelLoader.kt new file mode 100644 index 000000000..de56ee3fa --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/ModelLoader.kt @@ -0,0 +1,105 @@ +/* + * Minosoft + * Copyright (C) 2021 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.models + +import de.bixilon.minosoft.data.registries.ResourceLocation +import de.bixilon.minosoft.gui.rendering.models.builtin.BuiltinModels +import de.bixilon.minosoft.gui.rendering.models.unbaked.UnbakedBlockModel +import de.bixilon.minosoft.gui.rendering.models.unbaked.UnbakedItemModel +import de.bixilon.minosoft.gui.rendering.models.unbaked.UnbakedModel +import de.bixilon.minosoft.util.KUtil.fromJson +import de.bixilon.minosoft.util.KUtil.toResourceLocation +import de.bixilon.minosoft.util.KUtil.unsafeCast +import de.bixilon.minosoft.util.Util +import de.bixilon.minosoft.util.logging.Log +import de.bixilon.minosoft.util.logging.LogLevels +import de.bixilon.minosoft.util.logging.LogMessageType +import de.bixilon.minosoft.util.nbt.tag.NBTUtil.asCompound +import java.io.BufferedReader +import java.io.InputStreamReader +import java.util.zip.ZipEntry +import java.util.zip.ZipInputStream + +class ModelLoader( + val jar: ZipInputStream, +) { + private val unbakedBlockModels: MutableMap = BuiltinModels.BUILTIN_MODELS.toMutableMap() + private val blockStateJsons: MutableMap> = mutableMapOf() + private val modelJsons: MutableMap> = mutableMapOf() + + private fun loadJsons() { + // ToDo: Integrate in assets manager + var entry: ZipEntry? = jar.nextEntry + while (entry != null) { + if (!entry.name.startsWith("assets/minecraft/models/") && !entry.name.startsWith("assets/minecraft/blockstates/")) { + entry = jar.nextEntry + continue + } + val name = entry.name.removePrefix("assets/minecraft/").removeSuffix(".json") + val jsonString = Util.readReader(BufferedReader(InputStreamReader(jar)), false) + + val json = jsonString.fromJson().asCompound() + if (name.startsWith("models/")) { + modelJsons[name.removePrefix("models/").toResourceLocation()] = json + } else { + blockStateJsons[name.removePrefix("blockstates/").toResourceLocation()] = json + } + + + entry = jar.nextEntry + } + } + + fun load() { + loadJsons() + Log.log(LogMessageType.VERSION_LOADING, LogLevels.VERBOSE) { "Loaded ${blockStateJsons.size} block states and ${modelJsons.size} model jsons!" } + + + fun loadBlockModel(name: ResourceLocation, json: Map? = null): UnbakedModel { + unbakedBlockModels[name]?.let { return it.unsafeCast() } + val data = json ?: modelJsons[name] ?: error("Can not find json: $name") + + val parent = data["parent"]?.toResourceLocation()?.let { loadBlockModel(it) } + + val model = UnbakedBlockModel(parent, data) + + unbakedBlockModels[name] = model + return model + } + + + fun loadItemModel(name: ResourceLocation, json: Map? = null): UnbakedModel { + unbakedBlockModels[name]?.let { return it.unsafeCast() } + val data = json ?: modelJsons[name] ?: error("Can not find json: $name") + + val parent = data["parent"]?.toResourceLocation()?.let { loadItemModel(it) } + + val model = UnbakedItemModel(parent, data) + + unbakedBlockModels[name] = model + return model + } + + for ((name, json) in modelJsons) { + if (name.path.startsWith("block/")) { + loadBlockModel(name, json) + } else if (name.path.startsWith("item/")) { + loadItemModel(name, json) + } else { + TODO("Unknown block model type: $name") + } + } + Log.log(LogMessageType.VERSION_LOADING, LogLevels.VERBOSE) { "Done loading models!" } + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/builtin/BuiltinModels.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/builtin/BuiltinModels.kt new file mode 100644 index 000000000..3e4e95f2d --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/builtin/BuiltinModels.kt @@ -0,0 +1,24 @@ +/* + * Minosoft + * Copyright (C) 2021 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.models.builtin + +import de.bixilon.minosoft.data.registries.ResourceLocation +import de.bixilon.minosoft.gui.rendering.models.unbaked.UnbakedModel + +object BuiltinModels { + val BUILTIN_MODELS: Map = mapOf( + UnbakedBlockEntityModel.RESOURCE_LOCATION to UnbakedBlockEntityModel, + UnbakedGeneratedModel.RESOURCE_LOCATION to UnbakedGeneratedModel, + ) +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/builtin/UnbakedBlockEntityModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/builtin/UnbakedBlockEntityModel.kt new file mode 100644 index 000000000..c873d3679 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/builtin/UnbakedBlockEntityModel.kt @@ -0,0 +1,25 @@ +/* + * Minosoft + * Copyright (C) 2021 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.models.builtin + +import de.bixilon.minosoft.data.registries.CompanionResourceLocation +import de.bixilon.minosoft.data.registries.ResourceLocation +import de.bixilon.minosoft.gui.rendering.models.unbaked.UnbakedModel +import de.bixilon.minosoft.util.KUtil.toResourceLocation + +@Deprecated("TODO") +object UnbakedBlockEntityModel : UnbakedModel(null, mapOf()), CompanionResourceLocation { + override val RESOURCE_LOCATION: ResourceLocation = "minecraft:builtin/entity".toResourceLocation() + +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/builtin/UnbakedGeneratedModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/builtin/UnbakedGeneratedModel.kt new file mode 100644 index 000000000..bcdc1b6ee --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/builtin/UnbakedGeneratedModel.kt @@ -0,0 +1,25 @@ +/* + * Minosoft + * Copyright (C) 2021 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.models.builtin + +import de.bixilon.minosoft.data.registries.CompanionResourceLocation +import de.bixilon.minosoft.data.registries.ResourceLocation +import de.bixilon.minosoft.gui.rendering.models.unbaked.UnbakedModel +import de.bixilon.minosoft.util.KUtil.toResourceLocation + +@Deprecated("TODO") +object UnbakedGeneratedModel : UnbakedModel(null, mapOf()), CompanionResourceLocation { + override val RESOURCE_LOCATION: ResourceLocation = "minecraft:builtin/generated".toResourceLocation() + +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/display/ModelDisplay.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/display/ModelDisplay.kt new file mode 100644 index 000000000..9cf2af313 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/display/ModelDisplay.kt @@ -0,0 +1,37 @@ +/* + * Minosoft + * Copyright (C) 2021 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.models.display + +import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY +import de.bixilon.minosoft.gui.rendering.util.VecUtil.ONE +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.toVec3 +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.toVec3i +import glm_.vec3.Vec3 +import glm_.vec3.Vec3i + +data class ModelDisplay( + val rotation: Vec3i, + val translation: Vec3i, + val scale: Vec3, +) { + companion object { + operator fun invoke(data: Map): ModelDisplay { + return ModelDisplay( + rotation = data["rotation"]?.toVec3i() ?: Vec3i.EMPTY, + translation = data["translation"]?.toVec3i() ?: Vec3i.EMPTY, + scale = data["scale"]?.toVec3() ?: Vec3.ONE, + ) + } + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/display/ModelDisplayPositions.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/display/ModelDisplayPositions.kt new file mode 100644 index 000000000..37795759b --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/display/ModelDisplayPositions.kt @@ -0,0 +1,39 @@ +/* + * Minosoft + * Copyright (C) 2021 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.models.display + +import de.bixilon.minosoft.util.KUtil +import de.bixilon.minosoft.util.KUtil.unsafeCast +import de.bixilon.minosoft.util.enum.AliasableEnum +import de.bixilon.minosoft.util.enum.ValuesEnum + +enum class ModelDisplayPositions(vararg names: String = arrayOf()) : AliasableEnum { + THIRD_PERSON_RIGHT_HAND("thirdperson_righthand"), + THIRD_PERSON_LEFT_HAND("thirdperson_lefthand"), + FIRST_PERSON_RIGHT_HAND("firstperson_righthand"), + FIRST_PERSON_LEFT_HAND("firstperson_lefthand"), + GUI, + HEAD, + GROUND, + FIXED, + ; + + override val names: Array = names.unsafeCast() + + companion object : ValuesEnum { + override val VALUES: Array = values() + override val NAME_MAP: Map = KUtil.getEnumValues(VALUES) + + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/block/models/FaceSize.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/Model.kt similarity index 76% rename from src/main/java/de/bixilon/minosoft/gui/rendering/block/models/FaceSize.kt rename to src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/Model.kt index 3ccf1e297..35820a7b1 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/block/models/FaceSize.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/Model.kt @@ -11,11 +11,6 @@ * This software is not affiliated with Mojang AB, the original developer of Minecraft. */ -package de.bixilon.minosoft.gui.rendering.block.models +package de.bixilon.minosoft.gui.rendering.models.unbaked -import glm_.vec2.Vec2i - -data class FaceSize( - val start: Vec2i = Vec2i(0, 0), - val end: Vec2i = Vec2i(BlockModelElement.BLOCK_RESOLUTION, BlockModelElement.BLOCK_RESOLUTION), -) +interface Model diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/UnbakedBlockModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/UnbakedBlockModel.kt new file mode 100644 index 000000000..958a15093 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/UnbakedBlockModel.kt @@ -0,0 +1,23 @@ +/* + * Minosoft + * Copyright (C) 2021 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.models.unbaked + +import de.bixilon.minosoft.util.KUtil.toBoolean + +class UnbakedBlockModel( + parent: UnbakedModel?, + json: Map, +) : UnbakedModel(parent, json) { + val ambientOcclusion: Boolean = json["ambientocclusion"]?.toBoolean() ?: parent?.let { return@let if (parent is UnbakedBlockModel) parent.ambientOcclusion else null } ?: true +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/UnbakedItemModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/UnbakedItemModel.kt new file mode 100644 index 000000000..f97cfb646 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/UnbakedItemModel.kt @@ -0,0 +1,25 @@ +/* + * Minosoft + * Copyright (C) 2021 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.models.unbaked + +import de.bixilon.minosoft.gui.rendering.models.GUILights + +class UnbakedItemModel( + parent: UnbakedModel?, + json: Map, +) : UnbakedModel(parent, json) { + val guiLight: GUILights = json["gui_light"]?.toString()?.let { GUILights[it] } ?: parent?.let { return@let if (parent is UnbakedItemModel) parent.guiLight else null } ?: GUILights.SIDE + + // ToDo: Overrides (predicates) +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/UnbakedModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/UnbakedModel.kt new file mode 100644 index 000000000..b58079e59 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/UnbakedModel.kt @@ -0,0 +1,68 @@ +/* + * Minosoft + * Copyright (C) 2021 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.models.unbaked + +import de.bixilon.minosoft.gui.rendering.models.display.ModelDisplay +import de.bixilon.minosoft.gui.rendering.models.display.ModelDisplayPositions +import de.bixilon.minosoft.gui.rendering.models.unbaked.element.UnbakedElement +import de.bixilon.minosoft.util.KUtil.unsafeCast +import de.bixilon.minosoft.util.nbt.tag.NBTUtil.compoundCast +import de.bixilon.minosoft.util.nbt.tag.NBTUtil.listCast + +abstract class UnbakedModel( + parent: UnbakedModel?, + json: Map, +) : Model { + val display: Map + val elements: Set + + + init { + val display = parent?.display?.toMutableMap() ?: mutableMapOf() + + json["display"]?.compoundCast()?.let { + for ((name, value) in it) { + display[ModelDisplayPositions[name]] = ModelDisplay(data = value.unsafeCast()) + } + } + + this.display = display + } + + val textures: Map + + init { + val textures = parent?.textures?.toMutableMap() ?: mutableMapOf() + + json["textures"]?.compoundCast()?.let { + for ((name, value) in it) { + textures[name] = value.toString() + } + } + + this.textures = textures + } + + init { + val elements = parent?.elements?.toMutableSet() ?: mutableSetOf() + + json["elements"]?.listCast>()?.let { + for (element in it) { + elements += UnbakedElement(data = element) + } + } + + this.elements = elements + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/element/UnbakedElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/element/UnbakedElement.kt new file mode 100644 index 000000000..d105d20f8 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/element/UnbakedElement.kt @@ -0,0 +1,51 @@ +/* + * Minosoft + * Copyright (C) 2021 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.models.unbaked.element + +import de.bixilon.minosoft.data.direction.Directions +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.toVec3 +import de.bixilon.minosoft.util.KUtil.toBoolean +import de.bixilon.minosoft.util.KUtil.unsafeCast +import de.bixilon.minosoft.util.nbt.tag.NBTUtil.asCompound +import de.bixilon.minosoft.util.nbt.tag.NBTUtil.compoundCast +import glm_.vec3.Vec3 + +data class UnbakedElement( + val from: Vec3, + val to: Vec3, + val rotation: UnbakedElementRotation?, + val shade: Boolean, + val faces: Set, +) { + + companion object { + operator fun invoke(data: Map): UnbakedElement { + val faces: MutableSet = mutableSetOf() + + data["faces"].asCompound().let { + for ((direction, faceData) in it) { + faces += UnbakedElementFace(direction = Directions[direction], data = faceData.unsafeCast()) + } + } + + return UnbakedElement( + from = data["from"].toVec3(), + to = data["to"].toVec3(), + rotation = data["rotation"]?.compoundCast()?.let { return@let UnbakedElementRotation(data = it) }, + shade = data["shade"]?.toBoolean() ?: true, + faces = faces, + ) + } + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/element/UnbakedElementFace.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/element/UnbakedElementFace.kt new file mode 100644 index 000000000..e8469aea0 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/element/UnbakedElementFace.kt @@ -0,0 +1,47 @@ +/* + * Minosoft + * Copyright (C) 2021 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.models.unbaked.element + +import de.bixilon.minosoft.data.direction.Directions +import de.bixilon.minosoft.util.KUtil.toInt +import de.bixilon.minosoft.util.nbt.tag.NBTUtil.listCast +import glm_.vec2.Vec2 + +data class UnbakedElementFace( + val direction: Directions, + val uvStart: Vec2, + val uvEnd: Vec2, + val texture: String, + val cullFace: Directions?, + val rotation: Int, + val tintIndex: Int, +) { + companion object { + operator fun invoke(direction: Directions, data: Map): UnbakedElementFace { + val uv = data["uv"]?.listCast() + val uvStart = Vec2(uv?.get(0) ?: 0.0f, uv?.get(2) ?: 0.0f) + val uvEnd = Vec2(uv?.get(1) ?: 16.0f, uv?.get(3) ?: 16.0f) + + return UnbakedElementFace( + direction = direction, + uvStart = uvStart, + uvEnd = uvEnd, + texture = data["texture"].toString(), + cullFace = data["cullface"]?.toString()?.let { return@let Directions[it] }, + rotation = data["rotation"]?.toInt() ?: 0, + tintIndex = data["tintindex"]?.toInt() ?: -1, + ) + } + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/element/UnbakedElementRotation.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/element/UnbakedElementRotation.kt new file mode 100644 index 000000000..cf04a064d --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/element/UnbakedElementRotation.kt @@ -0,0 +1,40 @@ +/* + * Minosoft + * Copyright (C) 2021 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.models.unbaked.element + +import de.bixilon.minosoft.data.Axes +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.toVec3 +import de.bixilon.minosoft.util.KUtil.toBoolean +import de.bixilon.minosoft.util.KUtil.toFloat +import glm_.vec3.Vec3 + +data class UnbakedElementRotation( + val origin: Vec3, + val axis: Axes, + val angle: Float, + val rescale: Boolean, +) { + companion object { + + operator fun invoke(data: Map): UnbakedElementRotation { + return UnbakedElementRotation( + origin = data["origin"]?.toVec3() ?: Vec3.EMPTY, + axis = Axes[data["axis"].toString()], + angle = data["angle"].toFloat(), + rescale = data["rescale"]?.toBoolean() ?: false, + ) + } + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/util/VecUtil.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/util/VecUtil.kt index 994531268..080473511 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/util/VecUtil.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/util/VecUtil.kt @@ -13,9 +13,6 @@ package de.bixilon.minosoft.gui.rendering.util -import com.google.gson.JsonArray -import com.google.gson.JsonObject -import com.google.gson.JsonPrimitive import de.bixilon.minosoft.Minosoft import de.bixilon.minosoft.data.Axes import de.bixilon.minosoft.data.direction.AbstractDirection @@ -23,9 +20,7 @@ import de.bixilon.minosoft.data.direction.Directions import de.bixilon.minosoft.data.registries.AABB import de.bixilon.minosoft.data.registries.blocks.RandomOffsetTypes import de.bixilon.minosoft.data.registries.blocks.types.Block -import de.bixilon.minosoft.gui.rendering.block.models.BlockModelElement import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition -import de.bixilon.minosoft.util.KUtil.unsafeCast import glm_.func.common.ceil import glm_.func.common.clamp import glm_.func.common.floor @@ -58,19 +53,6 @@ object VecUtil { val Vec3d.Companion.ONE: Vec3d get() = Vec3d(1.0, 1.0, 1.0) - fun Any.toVec3(default: Vec3? = null): Vec3 { - return when (this) { - is List<*> -> Vec3(this[0] as Double, this[1] as Double, this[2] as Double) - is JsonArray -> Vec3(this[0].asFloat, this[1].asFloat, this[2].asFloat) - is JsonObject -> Vec3(this["x"]?.asFloat ?: 0, this["y"]?.asFloat ?: 0, this["z"]?.asFloat ?: 0) - is Map<*, *> -> Vec3(this["x"]?.unsafeCast() ?: 0, this["y"]?.unsafeCast() ?: 0, this["z"]?.unsafeCast() ?: 0) - is JsonPrimitive -> Vec3(this.asFloat) - is Float -> Vec3(this) - is Double -> Vec3(this) - else -> default ?: throw IllegalArgumentException("Not a Vec3!") - } - } - fun Vec3.clear() { x = 0.0f y = 0.0f @@ -204,10 +186,6 @@ object VecUtil { return this * cos + (axis cross this) * sin + axis * (axis dot this) * (1 - cos) } - fun List.readUV(): Pair { - return Pair(Vec2(this[0], BlockModelElement.BLOCK_RESOLUTION - this[1]), Vec2(this[2], BlockModelElement.BLOCK_RESOLUTION - this[3])) - } - fun Int.chunkPosition(multiplier: Int): Int { return if (this >= 0) { this / multiplier diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/util/vec/Vec2Util.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/util/vec/Vec2Util.kt index 509bcf959..3aa116b16 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/util/vec/Vec2Util.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/util/vec/Vec2Util.kt @@ -74,7 +74,7 @@ object Vec2Util { is List<*> -> Vec2i(this[0].toInt(), this[1].toInt()) is Map<*, *> -> Vec2i(this["x"]?.toInt() ?: 0, this["y"]?.toInt() ?: 0) is Number -> Vec2i(this.toInt()) - else -> default ?: throw IllegalArgumentException("Not a Vec2i!") + else -> default ?: throw IllegalArgumentException("Not a Vec2i: $this") } } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/util/vec/vec3/Vec3Util.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/util/vec/vec3/Vec3Util.kt new file mode 100644 index 000000000..8130610af --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/util/vec/vec3/Vec3Util.kt @@ -0,0 +1,39 @@ +/* + * Minosoft + * Copyright (C) 2021 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.util.vec.vec3 + +import de.bixilon.minosoft.util.KUtil.toFloat +import glm_.vec3.Vec3 + +object Vec3Util { + + val Vec3.Companion.MIN: Vec3 + get() = Vec3(Float.MIN_VALUE, Float.MIN_VALUE, Float.MIN_VALUE) + + val Vec3.Companion.EMPTY: Vec3 + get() = Vec3(0.0f, 0.0f, 0.0f) + + val Vec3.Companion.MAX: Vec3 + get() = Vec3(Float.MAX_VALUE, Float.MAX_VALUE, Float.MAX_VALUE) + + + fun Any?.toVec3(default: Vec3? = null): Vec3 { + return when (this) { + is List<*> -> Vec3(this[0].toFloat(), this[1].toFloat(), this[2].toFloat()) + is Map<*, *> -> Vec3(this["x"]?.toFloat() ?: 0.0f, this["y"]?.toFloat() ?: 0.0f, this["z"]?.toFloat() ?: 0.0f) + is Number -> Vec3(this.toFloat()) + else -> default ?: throw IllegalArgumentException("Not a Vec3: $this") + } + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/util/vec/vec3/Vec3iUtil.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/util/vec/vec3/Vec3iUtil.kt new file mode 100644 index 000000000..152b753cb --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/util/vec/vec3/Vec3iUtil.kt @@ -0,0 +1,40 @@ +/* + * Minosoft + * Copyright (C) 2021 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.util.vec.vec3 + +import de.bixilon.minosoft.util.KUtil.toInt +import glm_.vec3.Vec3 +import glm_.vec3.Vec3i + +object Vec3iUtil { + + val Vec3i.Companion.MIN: Vec3i + get() = Vec3i(Int.MIN_VALUE, Int.MIN_VALUE, Int.MIN_VALUE) + + val Vec3.Companion.EMPTY: Vec3i + get() = Vec3i(0, 0, 0) + + val Vec3.Companion.MAX: Vec3i + get() = Vec3i(Int.MAX_VALUE, Int.MAX_VALUE, Int.MAX_VALUE) + + + fun Any?.toVec3i(default: Vec3i? = null): Vec3i { + return when (this) { + is List<*> -> Vec3i(this[0].toInt(), this[1].toInt(), this[2].toInt()) + is Map<*, *> -> Vec3i(this["x"]?.toInt() ?: 0.0f, this["y"]?.toInt() ?: 0.0f, this["z"]?.toInt() ?: 0.0f) + is Number -> Vec3i(this.toInt()) + else -> default ?: throw IllegalArgumentException("Not a Vec3i: $this") + } + } +} diff --git a/src/main/java/de/bixilon/minosoft/util/ShutdownManager.kt b/src/main/java/de/bixilon/minosoft/util/ShutdownManager.kt index d6833d993..63beeed60 100644 --- a/src/main/java/de/bixilon/minosoft/util/ShutdownManager.kt +++ b/src/main/java/de/bixilon/minosoft/util/ShutdownManager.kt @@ -34,9 +34,9 @@ object ShutdownManager { connection.disconnect() } if (Minosoft.configInitialized) { - Minosoft.config.saveToFile() + // Minosoft.config.saveToFile() } - DefaultThreadPool.shutdown() + DefaultThreadPool.shutdownNow() // ToDo: Save config exitProcess(reason.exitCode) } diff --git a/src/main/java/de/bixilon/minosoft/util/Util.java b/src/main/java/de/bixilon/minosoft/util/Util.java index bfd348627..a1abf0e52 100644 --- a/src/main/java/de/bixilon/minosoft/util/Util.java +++ b/src/main/java/de/bixilon/minosoft/util/Util.java @@ -339,10 +339,13 @@ public final class Util { } @NotNull - public static JsonObject readJsonFromStream(@NotNull InputStream stream) throws IOException { + @Deprecated + public static JsonObject readJsonFromStream(@NotNull InputStream stream, boolean close) throws IOException { InputStreamReader reader = new InputStreamReader(stream); JsonObject json = JsonParser.parseReader(reader).getAsJsonObject(); - reader.close(); + if (close) { + reader.close(); + } return json; } } diff --git a/src/main/java/de/bixilon/minosoft/util/enum/ValuesEnum.kt b/src/main/java/de/bixilon/minosoft/util/enum/ValuesEnum.kt index 660bfeee4..2d29d3154 100644 --- a/src/main/java/de/bixilon/minosoft/util/enum/ValuesEnum.kt +++ b/src/main/java/de/bixilon/minosoft/util/enum/ValuesEnum.kt @@ -22,7 +22,7 @@ interface ValuesEnum> { } operator fun get(name: String): T { - return NAME_MAP[name]!! + return NAME_MAP[name] ?: throw IllegalArgumentException("Can not find enum value: $name") } fun next(current: T): T {