skeletal: automatic cube uv mapping

This commit is contained in:
Moritz Zwerger 2023-10-22 00:17:45 +02:00
parent b364512075
commit ee4720155d
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
4 changed files with 110 additions and 3 deletions

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* 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)))
}
}

View File

@ -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))
}
}

View File

@ -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<Directions, SkeletalFace>,
val children: Map<String, SkeletalElement> = emptyMap(),

View File

@ -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)
}
}