diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/block/WorldRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/block/WorldRenderer.kt index 467842cee..f06268f50 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/block/WorldRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/block/WorldRenderer.kt @@ -18,6 +18,8 @@ import de.bixilon.minosoft.data.assets.Resources import de.bixilon.minosoft.data.direction.Directions import de.bixilon.minosoft.data.direction.FakeDirection import de.bixilon.minosoft.data.registries.ResourceLocation +import de.bixilon.minosoft.data.registries.blocks.properties.BlockProperties +import de.bixilon.minosoft.data.registries.blocks.properties.MultipartDirectionParser import de.bixilon.minosoft.data.world.ChunkSection import de.bixilon.minosoft.data.world.World import de.bixilon.minosoft.gui.rendering.RenderWindow @@ -72,14 +74,14 @@ class WorldRenderer( val random = Random(0L) - val blockState1 = connection.registries.blockRegistry["end_portal_frame"]?.defaultState - val blockState2 = connection.registries.blockRegistry["oak_fence"]!!.defaultState//.withProperties(BlockProperties.FACING to Directions.SOUTH) + val blockState1 = connection.registries.blockRegistry["grass_block"]?.defaultState + val blockState2 = connection.registries.blockRegistry["oak_fence"]!!.defaultState.withProperties(BlockProperties.MULTIPART_SOUTH to MultipartDirectionParser.SIDE, BlockProperties.MULTIPART_NORTH to MultipartDirectionParser.SIDE, BlockProperties.MULTIPART_EAST to MultipartDirectionParser.SIDE, BlockProperties.MULTIPART_WEST to MultipartDirectionParser.SIDE) val section = ChunkSection(Array(4096) { if (it < 256) return@Array blockState2 else return@Array null when (random.nextInt(3)) { - 1 -> blockState2 + 1 -> blockState1 2 -> blockState2 - else -> blockState2 + else -> null } }) //val section = ChunkSection(Array(4096) { if (it < 1) blockState else null }) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/block/preparer/CullSectionPreparer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/block/preparer/CullSectionPreparer.kt index 7b806adf9..6d0a1893b 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/block/preparer/CullSectionPreparer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/block/preparer/CullSectionPreparer.kt @@ -59,7 +59,7 @@ class CullSectionPreparer( } random.setSeed(VecUtil.generatePositionHash(x, y, z)) - block?.model?.singleRender(Vec3i(x, y, z), mesh, random, neighbours, 0xFF, intArrayOf(0xF, 0xF, 0xF, 0xF)) + block?.model?.singleRender(Vec3i(x, y, z), mesh, random, neighbours, 0xFF, floatArrayOf(1.0f, 1.0f, 1.0f, 1.0f)) } } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/CullUtil.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/CullUtil.kt new file mode 100644 index 000000000..6e84970dd --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/CullUtil.kt @@ -0,0 +1,18 @@ +package de.bixilon.minosoft.gui.rendering.models + +object CullUtil { + + fun Array.canCull(size: FaceSize): Boolean { + for (faceSize in this) { + if ( + faceSize.start.x <= size.start.x + && faceSize.start.y <= size.start.y + && faceSize.end.x >= size.end.x + && faceSize.end.y >= size.end.y + ) { + return true + } + } + return false + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/MultipartBakedModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/MultipartBakedModel.kt index e91ff94c2..bca9bf896 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/MultipartBakedModel.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/MultipartBakedModel.kt @@ -17,19 +17,25 @@ import de.bixilon.minosoft.data.direction.Directions import de.bixilon.minosoft.data.registries.blocks.BlockState import de.bixilon.minosoft.data.world.light.LightAccessor import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMesh +import de.bixilon.minosoft.gui.rendering.models.FaceSize import de.bixilon.minosoft.gui.rendering.models.baked.block.BakedBlockModel import glm_.vec3.Vec3i import java.util.* class MultipartBakedModel( val models: Array, + val sizes: Array>, ) : BakedBlockModel { + override fun getSize(random: Random, direction: Directions): Array { + return sizes[direction.ordinal] + } + override fun getLight(position: Vec3i, random: Random, side: Directions, lightAccessor: LightAccessor): Int { return 0xFF } - override fun singleRender(position: Vec3i, mesh: ChunkSectionMesh, random: Random, neighbours: Array, light: Int, ambientLight: IntArray) { + override fun singleRender(position: Vec3i, mesh: ChunkSectionMesh, random: Random, neighbours: Array, light: Int, ambientLight: FloatArray) { for (model in models) { model.singleRender(position, mesh, random, neighbours, light, ambientLight) } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/WeightedBakedModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/WeightedBakedModel.kt index e11d9eaf1..d7b0e8034 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/WeightedBakedModel.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/WeightedBakedModel.kt @@ -17,6 +17,7 @@ import de.bixilon.minosoft.data.direction.Directions import de.bixilon.minosoft.data.registries.blocks.BlockState import de.bixilon.minosoft.data.world.light.LightAccessor import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMesh +import de.bixilon.minosoft.gui.rendering.models.FaceSize import de.bixilon.minosoft.gui.rendering.models.baked.block.BakedBlockModel import glm_.vec3.Vec3i import java.util.* @@ -36,6 +37,10 @@ class WeightedBakedModel( this.totalWeight = totalWeight } + override fun getSize(random: Random, direction: Directions): Array { + return getModel(random).getSize(random, direction) + } + private fun getModel(random: Random): BakedBlockModel { val totalWeight = abs(random.nextLong() % totalWeight) @@ -55,7 +60,7 @@ class WeightedBakedModel( return getModel(random).getLight(position, random, side, lightAccessor) } - override fun singleRender(position: Vec3i, mesh: ChunkSectionMesh, random: Random, neighbours: Array, light: Int, ambientLight: IntArray) { + override fun singleRender(position: Vec3i, mesh: ChunkSectionMesh, random: Random, neighbours: Array, light: Int, ambientLight: FloatArray) { getModel(random).singleRender(position, mesh, random, neighbours, light, ambientLight) } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/block/BakedBlockModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/block/BakedBlockModel.kt index 8275a8a13..2fc8b288b 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/block/BakedBlockModel.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/block/BakedBlockModel.kt @@ -17,14 +17,17 @@ import de.bixilon.minosoft.data.direction.Directions import de.bixilon.minosoft.data.registries.blocks.BlockState import de.bixilon.minosoft.data.world.light.LightAccessor import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMesh +import de.bixilon.minosoft.gui.rendering.models.FaceSize import de.bixilon.minosoft.gui.rendering.models.baked.BakedModel import glm_.vec3.Vec3i import java.util.* interface BakedBlockModel : BakedModel { + fun getSize(random: Random, direction: Directions): Array + // ToDo: Tint - fun singleRender(position: Vec3i, mesh: ChunkSectionMesh, random: Random, neighbours: Array, light: Int, ambientLight: IntArray) + fun singleRender(position: Vec3i, mesh: ChunkSectionMesh, random: Random, neighbours: Array, light: Int, ambientLight: FloatArray) // ToDo: Get ambient light fun getLight(position: Vec3i, random: Random, side: Directions, lightAccessor: LightAccessor): Int diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/block/BakedBlockStateModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/block/BakedBlockStateModel.kt index 728b0e0d3..e7a2d4e42 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/block/BakedBlockStateModel.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/block/BakedBlockStateModel.kt @@ -17,25 +17,38 @@ import de.bixilon.minosoft.data.direction.Directions import de.bixilon.minosoft.data.registries.blocks.BlockState import de.bixilon.minosoft.data.world.light.LightAccessor import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMesh +import de.bixilon.minosoft.gui.rendering.models.CullUtil.canCull +import de.bixilon.minosoft.gui.rendering.models.FaceSize import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.toVec3 import glm_.vec3.Vec3i import java.util.* class BakedBlockStateModel( val faces: Array>, + val sizes: Array>, ) : BakedBlockModel, GreedyBakedBlockModel { // ToDo: Greedy meshable override val canGreedyMesh: Boolean = true override val greedyMeshableFaces: BooleanArray = booleanArrayOf(true, false, true, true, true, true) - override fun singleRender(position: Vec3i, mesh: ChunkSectionMesh, random: Random, neighbours: Array, light: Int, ambientLight: IntArray) { + override fun getSize(random: Random, direction: Directions): Array { + return sizes[direction.ordinal] + } + + override fun singleRender(position: Vec3i, mesh: ChunkSectionMesh, random: Random, neighbours: Array, light: Int, ambientLight: FloatArray) { val floatPosition = position.toVec3() - for ((index, direction) in faces.withIndex()) { - val neighbour = neighbours[index] + for ((index, faces) in faces.withIndex()) { + val direction = Directions.VALUES[index] + val neighbour = neighbours[index]?.model + var neighbourSize: Array? = null if (neighbour != null) { - // continue + random.setSeed(0L) // ToDo + neighbourSize = neighbour.getSize(random, direction.inverted) } - for (face in direction) { - face.singleRender(floatPosition, mesh, neighbour, light, ambientLight) + for (face in faces) { + if (face.touching && neighbourSize != null && neighbourSize.isNotEmpty() && neighbourSize.canCull(face.faceSize)) { + continue + } + face.singleRender(floatPosition, mesh, light, ambientLight) } } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/block/BakedFace.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/block/BakedFace.kt index a3f987571..cda6195d8 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/block/BakedFace.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/block/BakedFace.kt @@ -15,7 +15,6 @@ package de.bixilon.minosoft.gui.rendering.models.baked.block import de.bixilon.minosoft.data.Axes import de.bixilon.minosoft.data.direction.Directions -import de.bixilon.minosoft.data.registries.blocks.BlockState import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMesh import de.bixilon.minosoft.gui.rendering.models.FaceSize import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture @@ -32,8 +31,9 @@ class BakedFace( val tintIndex: Int, val cullFace: Directions?, val texture: AbstractTexture, + val touching: Boolean, ) { - fun singleRender(position: Vec3, mesh: ChunkSectionMesh, neighbour: BlockState?, light: Int, ambientLight: IntArray) { + fun singleRender(position: Vec3, mesh: ChunkSectionMesh, light: Int, ambientLight: FloatArray) { // ToDo: Ambient light for ((index, textureIndex) in Mesh.QUAD_DRAW_ODER) { mesh.addVertex(positions[index] + position, uv[textureIndex], texture, null, light) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/block/UnbakedBlockStateModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/block/UnbakedBlockStateModel.kt index 519ff4612..eedd8020e 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/block/UnbakedBlockStateModel.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/block/UnbakedBlockStateModel.kt @@ -17,6 +17,7 @@ import de.bixilon.minosoft.data.Axes import de.bixilon.minosoft.data.direction.Directions import de.bixilon.minosoft.data.registries.ResourceLocation import de.bixilon.minosoft.gui.rendering.RenderWindow +import de.bixilon.minosoft.gui.rendering.models.FaceSize import de.bixilon.minosoft.gui.rendering.models.baked.block.BakedBlockModel import de.bixilon.minosoft.gui.rendering.models.baked.block.BakedBlockStateModel import de.bixilon.minosoft.gui.rendering.models.baked.block.BakedFace @@ -28,6 +29,7 @@ import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.texture import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.get import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.rad import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.toVec2iN +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.get import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.rotateAssign import de.bixilon.minosoft.util.KUtil.toBoolean import de.bixilon.minosoft.util.KUtil.toInt @@ -82,6 +84,7 @@ data class UnbakedBlockStateModel( val faces: Array> = Array(Directions.SIZE) { mutableListOf() } + val sizes: Array> = Array(Directions.SIZE) { mutableListOf() } for (element in model.elements) { val rescale = element.rotation?.rescale ?: false @@ -126,15 +129,20 @@ data class UnbakedBlockStateModel( } } - + val size = face.direction.getSize(element.from, element.to) + val touching = (if (face.direction.negative) element.from[face.direction.axis] else element.to[face.direction.axis] - 1.0f) == 0.0f + if (touching) { + sizes[direction.ordinal] += size + } faces[direction.ordinal] += BakedFace( - faceSize = face.direction.getSize(element.from, element.to), + faceSize = size, positions = positions, uv = texturePositions, shade = element.shade, tintIndex = face.tintIndex, cullFace = face.cullFace, texture = texture, + touching = touching, ) } } @@ -142,10 +150,15 @@ data class UnbakedBlockStateModel( val finalFaces: Array?> = arrayOfNulls(faces.size) for ((index, faceArray) in faces.withIndex()) { - finalFaces[index] = faceArray.toTypedArray() + finalFaces[index] = faceArray.reversed().toTypedArray() + } + val finalSizes: Array?> = arrayOfNulls(faces.size) + + for ((index, sizeArray) in sizes.withIndex()) { + finalSizes[index] = sizeArray.toTypedArray() } - val baked = BakedBlockStateModel(finalFaces.unsafeCast()) + val baked = BakedBlockStateModel(finalFaces.unsafeCast(), finalSizes.unsafeCast()) this.baked = baked return baked } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/block/UnbakedMultipartModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/block/UnbakedMultipartModel.kt index 0f361b93b..1e1798b44 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/block/UnbakedMultipartModel.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/unbaked/block/UnbakedMultipartModel.kt @@ -1,11 +1,14 @@ package de.bixilon.minosoft.gui.rendering.models.unbaked.block +import de.bixilon.minosoft.data.direction.Directions import de.bixilon.minosoft.gui.rendering.RenderWindow +import de.bixilon.minosoft.gui.rendering.models.FaceSize import de.bixilon.minosoft.gui.rendering.models.baked.BakedModel import de.bixilon.minosoft.gui.rendering.models.baked.MultipartBakedModel import de.bixilon.minosoft.gui.rendering.models.baked.block.BakedBlockModel import de.bixilon.minosoft.gui.rendering.models.unbaked.UnbakedModel import de.bixilon.minosoft.util.KUtil.unsafeCast +import java.util.* class UnbakedMultipartModel( val models: Set, @@ -13,12 +16,25 @@ class UnbakedMultipartModel( override fun bake(renderWindow: RenderWindow): BakedModel { val baked: Array = arrayOfNulls(this.models.size) + val sizes: Array> = Array(Directions.SIZE) { mutableListOf() } - var index = 0 - for (model in this.models) { - baked[index++] = model.bake(renderWindow) + for ((index, model) in this.models.withIndex()) { + val bakedModel = model.bake(renderWindow) + for (direction in Directions.VALUES) { + sizes[direction.ordinal] += bakedModel.getSize(RANDOM, direction) // There is no random here! + } + baked[index] = bakedModel + } + val finalFaces: Array?> = arrayOfNulls(Directions.SIZE) + for (index in 0 until Directions.SIZE) { + finalFaces[index] = sizes[index].toTypedArray() } - return MultipartBakedModel(baked.unsafeCast()) + + return MultipartBakedModel(baked.unsafeCast(), finalFaces.unsafeCast()) + } + + private companion object { + private val RANDOM = Random(0L) } }