From b95129b7af36c7f70911ea4f013ba022de9345f1 Mon Sep 17 00:00:00 2001 From: Bixilon Date: Tue, 28 Mar 2023 13:01:04 +0200 Subject: [PATCH] cuboid: rotate up, down --- .../models/baked/BakedModelTestUtil.kt | 10 ++--- .../rendering/models/baked/CuboidBakeTest.kt | 35 ++++++++++++++++ .../exceptions/ChunkNotLoadedException.kt | 16 -------- .../state/apply/SingleBlockStateApply.kt | 41 ++++++++++++++++++- .../models/block/state/baked/BakingUtil.kt | 4 +- .../block/state/variant/VariantBlockModel.kt | 2 +- 6 files changed, 82 insertions(+), 26 deletions(-) delete mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/exceptions/ChunkNotLoadedException.kt diff --git a/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/models/baked/BakedModelTestUtil.kt b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/models/baked/BakedModelTestUtil.kt index f278ab820..187073025 100644 --- a/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/models/baked/BakedModelTestUtil.kt +++ b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/models/baked/BakedModelTestUtil.kt @@ -53,16 +53,14 @@ object BakedModelTestUtil { return map } - fun BakedModel.assertFace(direction: Directions, positions: FloatArray, uv: FloatArray, shade: Float, texture: String? = null) { + fun BakedModel.assertFace(direction: Directions, positions: FloatArray, uv: FloatArray? = null, shade: Float? = null, texture: String? = null) { val faces = this.faces[direction.ordinal] if (faces.size != 1) throw IllegalArgumentException("Model has more/less than once face!") val face = faces.first() Assert.assertEquals(face.positions, positions, "Vertices mismatch") - Assert.assertEquals(face.uv, uv, "UV mismatch") - Assert.assertEquals(face.shade, shade, "Shade mismatch") - if (texture != null) { - Assert.assertEquals(face.texture.resourceLocation, texture.toResourceLocation().texture(), "Texture mismatch") - } + uv?.let { Assert.assertEquals(face.uv, it, "UV mismatch") } + shade?.let { Assert.assertEquals(face.shade, it, "Shade mismatch") } + texture?.toResourceLocation()?.texture()?.let { Assert.assertEquals(face.texture.resourceLocation, it, "Texture mismatch") } } } diff --git a/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/models/baked/CuboidBakeTest.kt b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/models/baked/CuboidBakeTest.kt index 51e0aacab..9b166c801 100644 --- a/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/models/baked/CuboidBakeTest.kt +++ b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/models/baked/CuboidBakeTest.kt @@ -23,6 +23,7 @@ import de.bixilon.minosoft.gui.rendering.models.block.BlockModel import de.bixilon.minosoft.gui.rendering.models.block.element.ModelElement import de.bixilon.minosoft.gui.rendering.models.block.element.ModelElement.Companion.BLOCK_SIZE import de.bixilon.minosoft.gui.rendering.models.block.state.apply.SingleBlockStateApply +import de.bixilon.minosoft.gui.rendering.models.block.state.baked.BakedModel import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.texture import org.testng.annotations.Test @@ -70,4 +71,38 @@ class CuboidBakeTest { baked.assertFace(Directions.WEST, block(2, 2, 1, 2, 15, 1, 2, 15, 16, 2, 2, 16), block(1, 2, 1, 15, 16, 15, 16, 2), 0.6f) baked.assertFace(Directions.EAST, block(13, 2, 1, 13, 2, 16, 13, 15, 16, 13, 15, 1), block(15, 2, 0, 2, 0, 15, 15, 15), 0.6f) } + + fun rotatedUp() { + val from = Vec3(6, 0, 6) / BLOCK_SIZE + val to = Vec3(10, 16, 16) / BLOCK_SIZE + + fun bake(rotation: Int): BakedModel { + val model = SingleBlockStateApply(BlockModel(elements = listOf(ModelElement(from, to, faces = mapOf(Directions.UP to createFaces(from, to)[Directions.UP]!!))), textures = mapOf("test" to minecraft("block/test").texture())), y = rotation) + + return model.bake(createTextureManager("block/test"))!! + } + + + bake(0).assertFace(Directions.UP, block(6, 16, 6, 10, 16, 6, 10, 16, 16, 6, 16, 16)) + bake(1).assertFace(Directions.UP, block(0, 16, 6, 10, 16, 6, 10, 16, 10, 0, 16, 10)) + bake(2).assertFace(Directions.UP, block(6, 16, 0, 10, 16, 0, 10, 16, 10, 6, 16, 10)) + bake(3).assertFace(Directions.UP, block(6, 16, 6, 16, 16, 6, 16, 16, 10, 6, 16, 10)) + } + + fun rotatedDown() { + val from = Vec3(6, 0, 6) / BLOCK_SIZE + val to = Vec3(10, 16, 16) / BLOCK_SIZE + + fun bake(rotation: Int): BakedModel { + val model = SingleBlockStateApply(BlockModel(elements = listOf(ModelElement(from, to, faces = mapOf(Directions.DOWN to createFaces(from, to)[Directions.DOWN]!!))), textures = mapOf("test" to minecraft("block/test").texture())), y = rotation) + + return model.bake(createTextureManager("block/test"))!! + } + + + bake(0).assertFace(Directions.DOWN, block(6, 0, 6, 6, 0, 16, 10, 0, 16, 10, 0, 6)) + bake(1).assertFace(Directions.DOWN, block(0, 0, 6, 0, 0, 10, 10, 0, 10, 10, 0, 6)) + bake(2).assertFace(Directions.DOWN, block(6, 0, 0, 6, 0, 10, 10, 0, 10, 10, 0, 0)) + bake(3).assertFace(Directions.DOWN, block(6, 0, 6, 6, 0, 10, 16, 0, 10, 16, 0, 6)) + } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/exceptions/ChunkNotLoadedException.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/exceptions/ChunkNotLoadedException.kt deleted file mode 100644 index a06cf53cb..000000000 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/exceptions/ChunkNotLoadedException.kt +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Minosoft - * Copyright (C) 2020 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.exceptions - -class ChunkNotLoadedException(message: String = "Chunk is unloaded") : Exception(message) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/apply/SingleBlockStateApply.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/apply/SingleBlockStateApply.kt index aca8b9a89..8636d082b 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/apply/SingleBlockStateApply.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/apply/SingleBlockStateApply.kt @@ -38,6 +38,41 @@ data class SingleBlockStateApply( val y: Int = 0, ) : BlockStateApply { + /* + private fun FloatArray.rotateUp(count: Int): FloatArray { + if (count == 0) return this + val a = this.map { it - 0.5f }.toFloatArray() + val b = when (count) { + 1 -> floatArrayOf(a[2], a[1], -a[0], a[5], a[4], -a[3], a[8], a[7], -a[6], a[11], a[10], -a[9]) + else -> this + } + val c = b.pushRight(3, -count) + val d = c.map { it + 0.5f }.toFloatArray() + + return d + } + */ + + private fun FloatArray.rotateOffset(offset: Int) { + val x = this[offset + 0] + val y = this[offset + 2] + + this[offset + 0] = -y + 1.0f + this[offset + 2] = x + } + + private fun FloatArray.rotateY(count: Int, negative: Boolean): FloatArray { + if (count == 0) return this + + for (c in 0 until count) { + for (i in 0 until 4) { + rotateOffset(i * 3) + } + } + + return this.pushRight(3, if (negative) -count else count) + } + override fun bake(textures: TextureManager): BakedModel? { if (model.elements == null) return null @@ -53,7 +88,11 @@ data class SingleBlockStateApply( rotatedDirection = rotatedDirection.rotateY(this.y) } - val positions = positions(rotatedDirection, element.from, element.to) + + var positions = positions(rotatedDirection, element.from, element.to) + if (direction.axis == Axes.Y) { + positions = positions.rotateY(y, direction.negative) + } var uv = face.uv.toArray(rotatedDirection, face.rotation) if (direction.axis == Axes.Y && y != 0 && !uvLock) { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/baked/BakingUtil.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/baked/BakingUtil.kt index d7413b143..6c3c54c0d 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/baked/BakingUtil.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/baked/BakingUtil.kt @@ -22,8 +22,8 @@ object BakingUtil { fun positions(direction: Directions, from: Vec3, to: Vec3): FloatArray { return when (direction) { // @formatter:off - Directions.DOWN -> floatArrayOf(from.x, from.y, from.z, /**/ to.x, from.y, from.z, /**/ to.x, from.y, to.z, /**/ from.x, from.y, to.z ) - Directions.UP -> floatArrayOf(from.x, to.y, from.z, /**/ from.x, to.y, to.z, /**/ to.x, to.y, to.z, /**/ to.x, to.y, from.z ) + Directions.DOWN -> floatArrayOf(from.x, from.y, from.z, /**/ from.x, from.y, to.z, /**/ to.x, from.y, to.z, /**/ to.x, from.y, from.z ) + Directions.UP -> floatArrayOf(from.x, to.y, from.z, /**/ to.x, to.y, from.z, /**/ to.x, to.y, to.z, /**/ from.x, to.y, to.z ) Directions.NORTH -> floatArrayOf(from.x, from.y, from.z, /**/ to.x, from.y, from.z, /**/ to.x, to.y, from.z, /**/ from.x, to.y, from.z ) Directions.SOUTH -> floatArrayOf(from.x, from.y, to.z, /**/ from.x, to.y, to.z, /**/ to.x, to.y, to.z, /**/ to.x, from.y, to.z ) Directions.WEST -> floatArrayOf(from.x, from.y, from.z, /**/ from.x, to.y, from.z, /**/ from.x, to.y, to.z, /**/ from.x, from.y, to.z ) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/variant/VariantBlockModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/variant/VariantBlockModel.kt index c500b9c15..113a781bf 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/variant/VariantBlockModel.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/variant/VariantBlockModel.kt @@ -44,7 +44,7 @@ interface VariantBlockModel : DirectBlockModel { for ((variant, entry) in data) { val apply = BlockStateApply.deserialize(loader, entry.asJsonObject()) ?: continue - if (variant == "") { + if (variant == "" || variant == "normal") { // no further conditions return SingleVariantBlockModel(apply) }