cuboid: rotate up, down

This commit is contained in:
Bixilon 2023-03-28 13:01:04 +02:00
parent 0a435274b5
commit b95129b7af
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
6 changed files with 82 additions and 26 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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