diff --git a/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/models/util/CuboidUtilTest.kt b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/models/util/CuboidUtilTest.kt new file mode 100644 index 000000000..3e9895b2f --- /dev/null +++ b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/models/util/CuboidUtilTest.kt @@ -0,0 +1,51 @@ +/* + * Minosoft + * Copyright (C) 2020-2023 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.util + +import de.bixilon.kotlinglm.vec2.Vec2i +import de.bixilon.kotlinglm.vec3.Vec3 +import de.bixilon.minosoft.data.direction.Directions +import de.bixilon.minosoft.gui.rendering.models.block.element.face.FaceUV +import org.testng.Assert.assertEquals +import org.testng.annotations.Test + +@Test(groups = ["rendering", "models"]) +class CuboidUtilTest { + + fun `simple uv`() { + val from = Vec3(-7, 0, -7) + val to = Vec3(7, 10, 7) + val offset = Vec2i(0, 19) + + assertEquals(CuboidUtil.cubeUV(offset, from, to, Directions.DOWN), FaceUV(floatArrayOf(14f, 19f, 28f, 33f))) + assertEquals(CuboidUtil.cubeUV(offset, from, to, Directions.UP), FaceUV(floatArrayOf(28f, 33f, 42f, 19f))) + assertEquals(CuboidUtil.cubeUV(offset, from, to, Directions.NORTH), FaceUV(floatArrayOf(42f, 33f, 56f, 43f))) + assertEquals(CuboidUtil.cubeUV(offset, from, to, Directions.SOUTH), FaceUV(floatArrayOf(14f, 33f, 28f, 43f))) + assertEquals(CuboidUtil.cubeUV(offset, from, to, Directions.WEST), FaceUV(floatArrayOf(28f, 33f, 42f, 43f))) + assertEquals(CuboidUtil.cubeUV(offset, from, to, Directions.EAST), FaceUV(floatArrayOf(0f, 33f, 14f, 43f))) + } + + fun `not same size uv`() { + val from = Vec3(-1, 0, 0) + val to = Vec3(1, 4, 1) + val offset = Vec2i(0, 0) + + assertEquals(CuboidUtil.cubeUV(offset, from, to, Directions.DOWN), FaceUV(floatArrayOf(1f, 0f, 3f, 1f))) + assertEquals(CuboidUtil.cubeUV(offset, from, to, Directions.UP), FaceUV(floatArrayOf(3f, 1f, 5f, 0f))) + assertEquals(CuboidUtil.cubeUV(offset, from, to, Directions.NORTH), FaceUV(floatArrayOf(4f, 1f, 6f, 5f))) + assertEquals(CuboidUtil.cubeUV(offset, from, to, Directions.SOUTH), FaceUV(floatArrayOf(1f, 1f, 3f, 5f))) + assertEquals(CuboidUtil.cubeUV(offset, from, to, Directions.WEST), FaceUV(floatArrayOf(3f, 1f, 4f, 5f))) + assertEquals(CuboidUtil.cubeUV(offset, from, to, Directions.EAST), FaceUV(floatArrayOf(0f, 1f, 1f, 5f))) + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/util/CuboidUtil.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/util/CuboidUtil.kt index 6a3d8e12d..6d83b94a9 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/util/CuboidUtil.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/util/CuboidUtil.kt @@ -13,9 +13,14 @@ package de.bixilon.minosoft.gui.rendering.models.util +import de.bixilon.kotlinglm.vec2.Vec2 +import de.bixilon.kotlinglm.vec2.Vec2i import de.bixilon.kotlinglm.vec3.Vec3 +import de.bixilon.kotlinglm.vec3.Vec3i +import de.bixilon.minosoft.data.Axes import de.bixilon.minosoft.data.direction.Directions import de.bixilon.minosoft.gui.rendering.models.block.element.FaceVertexData +import de.bixilon.minosoft.gui.rendering.models.block.element.face.FaceUV object CuboidUtil { @@ -31,4 +36,50 @@ object CuboidUtil { // @formatter:on } } + + fun cubeUV(offset: Vec2i, from: Vec3, to: Vec3, direction: Directions): FaceUV { + val cube = Vec3i(to - from) + + val uv = Vec2i(offset) + val size = when (direction.axis) { + Axes.Y -> Vec2i(cube.x, cube.z) + Axes.Z -> Vec2i(cube.x, cube.y) + Axes.X -> Vec2i(cube.z, cube.y) + } + + when (direction) { + Directions.DOWN -> { + uv.x += cube.z + } + + Directions.UP -> { + uv.x += cube.z + cube.x + // flip y coordinate + uv.y += cube.z + size.y = -cube.z + } + + Directions.NORTH -> { + uv.x += cube.z + cube.x + cube.z + uv.y += cube.z + } + + Directions.SOUTH -> { + uv.x += cube.z + uv.y += cube.z + } + + Directions.WEST -> { + uv.x += cube.z + cube.x + uv.y += cube.z + } + + Directions.EAST -> { + uv.y += cube.z + } + } + + + return FaceUV(Vec2(uv.x, uv.y), Vec2(uv.x + size.x, uv.y + size.y)) + } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/elements/SkeletalElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/elements/SkeletalElement.kt index b3028d04b..f38082858 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/elements/SkeletalElement.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/elements/SkeletalElement.kt @@ -13,6 +13,7 @@ package de.bixilon.minosoft.gui.rendering.skeletal.model.elements +import de.bixilon.kotlinglm.vec2.Vec2i import de.bixilon.kotlinglm.vec3.Vec3 import de.bixilon.minosoft.data.direction.Directions import de.bixilon.minosoft.data.registries.identified.ResourceLocation @@ -30,6 +31,7 @@ data class SkeletalElement( val inflate: Float = 0.0f, val enabled: Boolean = true, val texture: ResourceLocation? = null, + val uv: Vec2i? = null, val transform: String? = null, val faces: Map, val children: Map = emptyMap(), diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/elements/SkeletalFace.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/elements/SkeletalFace.kt index f7f9b1160..697139418 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/elements/SkeletalFace.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/model/elements/SkeletalFace.kt @@ -26,10 +26,11 @@ import de.bixilon.minosoft.gui.rendering.skeletal.baked.SkeletalBakeContext import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.rotateAssign data class SkeletalFace( - val uv: FaceUV, + val uv: FaceUV? = null, val texture: ResourceLocation? = null, ) { + fun bake(context: SkeletalBakeContext, direction: Directions, element: SkeletalElement, transform: Int) { val from = context.offset + (element.from - context.inflate) / BLOCK_SIZE val to = context.offset + (element.to + context.inflate) / BLOCK_SIZE @@ -38,7 +39,9 @@ data class SkeletalFace( val texture = context.textures[texture ?: context.texture ?: throw IllegalStateException("Element has no texture set!")] ?: throw IllegalStateException("Texture not found!") // TODO: why flip on x? - val uv = FaceUV( + val uv = this.uv ?: CuboidUtil.cubeUV(element.uv!!, element.from, element.to, direction) + + val uvData = FaceUV( texture.texture.transformUV(Vec2(uv.end.x, uv.start.y) / texture.properties.resolution), texture.texture.transformUV(Vec2(uv.start.x, uv.end.y) / texture.properties.resolution), ).toArray(direction, 0) @@ -57,6 +60,6 @@ data class SkeletalFace( } } - context.consumer.addQuad(positions, uv, transform, texture.texture) + context.consumer.addQuad(positions, uvData, transform, texture.texture) } }