diff --git a/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/models/block/state/baked/cull/FaceCullingTest.kt b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/models/block/state/baked/cull/FaceCullingTest.kt index 705950b41..9acbf01c6 100644 --- a/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/models/block/state/baked/cull/FaceCullingTest.kt +++ b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/models/block/state/baked/cull/FaceCullingTest.kt @@ -15,9 +15,14 @@ package de.bixilon.minosoft.gui.rendering.models.block.state.baked.cull import de.bixilon.kotlinglm.vec2.Vec2 import de.bixilon.kotlinglm.vec2.Vec2i +import de.bixilon.kutil.exception.Broken +import de.bixilon.minosoft.data.direction.Directions +import de.bixilon.minosoft.data.registries.blocks.settings.BlockSettings import de.bixilon.minosoft.data.registries.blocks.state.BlockState +import de.bixilon.minosoft.data.registries.blocks.types.Block import de.bixilon.minosoft.data.registries.identified.Namespaces.minosoft import de.bixilon.minosoft.gui.rendering.models.block.state.baked.BakedFace +import de.bixilon.minosoft.gui.rendering.models.block.state.baked.BakedModel import de.bixilon.minosoft.gui.rendering.models.block.state.baked.SideSize import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureTransparencies import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.MemoryTexture @@ -33,26 +38,34 @@ class FaceCullingTest { } private fun createNeighbour(size: SideSize? = SideSize(arrayOf(SideSize.FaceSize(Vec2(0), Vec2(1)))), transparency: TextureTransparencies = TextureTransparencies.OPAQUE): BlockState { - TODO() + val block = object : Block(minosoft("dummy"), BlockSettings()) { + override val hardness: Float get() = Broken() + } + + val state = BlockState(block, 0) + + state.model = BakedModel(emptyArray(), arrayOf(size, size, size, size, size, size), null) + + return state } fun noNeighbour() { val face = createFace() - assertFalse(FaceCulling.canCull(face, null)) + assertFalse(FaceCulling.canCull(face, Directions.DOWN, null)) } @Test fun selfNotTouching() { val face = createFace(null) val neighbour = createNeighbour() - assertFalse(FaceCulling.canCull(face, neighbour)) + assertFalse(FaceCulling.canCull(face, Directions.DOWN, neighbour)) } @Test fun neighbourNotTouching() { val face = createFace() val neighbour = createNeighbour(null) - assertFalse(FaceCulling.canCull(face, neighbour)) + assertFalse(FaceCulling.canCull(face, Directions.DOWN, neighbour)) } // TODO: force no cull (e.g. leaves), mix of transparency, mix of side sizes diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/baked/BakedModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/baked/BakedModel.kt index 77cab20a8..cfae52efd 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/baked/BakedModel.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/baked/BakedModel.kt @@ -14,6 +14,7 @@ package de.bixilon.minosoft.gui.rendering.models.block.state.baked import de.bixilon.kotlinglm.vec3.Vec3i +import de.bixilon.minosoft.data.direction.Directions import de.bixilon.minosoft.data.registries.blocks.state.BlockState import de.bixilon.minosoft.data.world.positions.BlockPosition import de.bixilon.minosoft.gui.rendering.models.block.state.baked.cull.FaceCulling @@ -24,21 +25,24 @@ import java.util.* class BakedModel( val faces: Array>, - val sizes: Array, + val sizes: Array, val particle: AbstractTexture?, ) : BlockRender { + override fun getSize(direction: Directions) = sizes[direction.ordinal] + override fun getParticleTexture(random: Random?, position: Vec3i) = particle override fun render(position: BlockPosition, offset: FloatArray, mesh: WorldMesh, random: Random?, state: BlockState, neighbours: Array, light: ByteArray, tints: IntArray?): Boolean { var rendered = false - for ((direction, faces) in faces.withIndex()) { - val neighbour = neighbours[direction] + for ((directionIndex, faces) in faces.withIndex()) { + val neighbour = neighbours[directionIndex] + val direction = Directions.VALUES[directionIndex].inverted for (face in faces) { - if (FaceCulling.canCull(face, neighbour)) { + if (FaceCulling.canCull(face, direction, neighbour)) { continue } face.render(offset, mesh, light, tints) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/baked/SideSize.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/baked/SideSize.kt index 72e2e2d5c..514e0e233 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/baked/SideSize.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/baked/SideSize.kt @@ -19,6 +19,10 @@ class SideSize( val sizes: Array, ) { + init { + if (sizes.isEmpty()) throw IllegalCallerException("sizes is empty!") + } + class FaceSize( val start: Vec2, diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/baked/cull/FaceCulling.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/baked/cull/FaceCulling.kt index 801feb180..88795a40e 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/baked/cull/FaceCulling.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/baked/cull/FaceCulling.kt @@ -13,15 +13,19 @@ package de.bixilon.minosoft.gui.rendering.models.block.state.baked.cull +import de.bixilon.minosoft.data.direction.Directions import de.bixilon.minosoft.data.registries.blocks.state.BlockState import de.bixilon.minosoft.gui.rendering.models.block.state.baked.BakedFace object FaceCulling { - fun canCull(face: BakedFace, neighbour: BlockState?): Boolean { + fun canCull(face: BakedFace, direction: Directions, neighbour: BlockState?): Boolean { if (neighbour == null) return false if (!face.touchingSide) return false + val model = neighbour.model ?: return false + val size = model.getSize(direction) ?: return false + return true // TODO } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/builder/BuiltModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/builder/BuiltModel.kt index a58730a4b..4856fe415 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/builder/BuiltModel.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/builder/BuiltModel.kt @@ -37,4 +37,6 @@ class BuiltModel( return rendered } + + // TODO: getSize/culling support } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/render/BlockRender.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/render/BlockRender.kt index 1107bf6e4..d0de08177 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/render/BlockRender.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/render/BlockRender.kt @@ -14,8 +14,10 @@ package de.bixilon.minosoft.gui.rendering.models.block.state.render import de.bixilon.kotlinglm.vec3.Vec3i +import de.bixilon.minosoft.data.direction.Directions import de.bixilon.minosoft.data.registries.blocks.state.BlockState import de.bixilon.minosoft.data.world.positions.BlockPosition +import de.bixilon.minosoft.gui.rendering.models.block.state.baked.SideSize import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh import java.util.* @@ -24,4 +26,6 @@ interface BlockRender { fun getParticleTexture(random: Random?, position: Vec3i): AbstractTexture? = null fun render(position: BlockPosition, offset: FloatArray, mesh: WorldMesh, random: Random?, state: BlockState, neighbours: Array, light: ByteArray, tints: IntArray?): Boolean + + fun getSize(direction: Directions): SideSize? = null } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/render/WeightedBlockRender.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/render/WeightedBlockRender.kt index 54d5c2c92..4f5129b1b 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/render/WeightedBlockRender.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/render/WeightedBlockRender.kt @@ -15,10 +15,12 @@ package de.bixilon.minosoft.gui.rendering.models.block.state.render import de.bixilon.kotlinglm.vec3.Vec3i import de.bixilon.kutil.exception.Broken +import de.bixilon.minosoft.data.direction.Directions import de.bixilon.minosoft.data.registries.blocks.state.BlockState import de.bixilon.minosoft.data.world.positions.BlockPosition import de.bixilon.minosoft.data.world.positions.BlockPositionUtil.positionHash import de.bixilon.minosoft.gui.rendering.models.block.state.baked.BakedModel +import de.bixilon.minosoft.gui.rendering.models.block.state.baked.SideSize import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh import java.util.* @@ -28,7 +30,11 @@ class WeightedBlockRender( val models: Array, val totalWeight: Int, ) : BlockRender { + private val size = models.getSize() + override fun getSize(direction: Directions): SideSize? { + return size[direction.ordinal] // TODO: get random block model + } private fun getModel(random: Random?, position: BlockPosition): BlockRender { if (random == null) return models.first().model @@ -59,4 +65,33 @@ class WeightedBlockRender( val weight: Int, val model: BakedModel, ) + + private fun Array.getSize(): Array { + val sizes: Array = arrayOfNulls(Directions.SIZE) + val skip = BooleanArray(Directions.SIZE) + + for ((_, model) in this) { + for (direction in Directions) { + if (skip[direction.ordinal]) continue + + val current = sizes[direction.ordinal] + val size = model.getSize(direction) + if (current == null) { + sizes[direction.ordinal] = size + continue + } + if (current != size) { + skip[direction.ordinal] = true + continue + } + } + } + + for ((index, skip) in skip.withIndex()) { + if (!skip) continue + sizes[index] = null + } + + return sizes + } }