wip face culling

This commit is contained in:
Bixilon 2023-06-21 22:16:00 +02:00
parent 097e72906c
commit 110bf94706
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
7 changed files with 75 additions and 9 deletions

View File

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

View File

@ -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<Array<BakedFace>>,
val sizes: Array<SideSize>,
val sizes: Array<SideSize?>,
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<BlockState?>, 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)

View File

@ -19,6 +19,10 @@ class SideSize(
val sizes: Array<FaceSize>,
) {
init {
if (sizes.isEmpty()) throw IllegalCallerException("sizes is empty!")
}
class FaceSize(
val start: Vec2,

View File

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

View File

@ -37,4 +37,6 @@ class BuiltModel(
return rendered
}
// TODO: getSize/culling support
}

View File

@ -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<BlockState?>, light: ByteArray, tints: IntArray?): Boolean
fun getSize(direction: Directions): SideSize? = null
}

View File

@ -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<WeightedEntry>,
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<WeightedEntry>.getSize(): Array<SideSize?> {
val sizes: Array<SideSize?> = 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
}
}