mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-16 10:55:01 -04:00
face culling
This commit is contained in:
parent
486da0eda1
commit
b811a95059
@ -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 })
|
||||
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,18 @@
|
||||
package de.bixilon.minosoft.gui.rendering.models
|
||||
|
||||
object CullUtil {
|
||||
|
||||
fun Array<FaceSize>.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
|
||||
}
|
||||
}
|
@ -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<BakedBlockModel>,
|
||||
val sizes: Array<Array<FaceSize>>,
|
||||
) : BakedBlockModel {
|
||||
|
||||
override fun getSize(random: Random, direction: Directions): Array<FaceSize> {
|
||||
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<BlockState?>, light: Int, ambientLight: IntArray) {
|
||||
override fun singleRender(position: Vec3i, mesh: ChunkSectionMesh, random: Random, neighbours: Array<BlockState?>, light: Int, ambientLight: FloatArray) {
|
||||
for (model in models) {
|
||||
model.singleRender(position, mesh, random, neighbours, light, ambientLight)
|
||||
}
|
||||
|
@ -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<FaceSize> {
|
||||
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<BlockState?>, light: Int, ambientLight: IntArray) {
|
||||
override fun singleRender(position: Vec3i, mesh: ChunkSectionMesh, random: Random, neighbours: Array<BlockState?>, light: Int, ambientLight: FloatArray) {
|
||||
getModel(random).singleRender(position, mesh, random, neighbours, light, ambientLight)
|
||||
}
|
||||
|
||||
|
@ -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<FaceSize>
|
||||
|
||||
// ToDo: Tint
|
||||
fun singleRender(position: Vec3i, mesh: ChunkSectionMesh, random: Random, neighbours: Array<BlockState?>, light: Int, ambientLight: IntArray)
|
||||
fun singleRender(position: Vec3i, mesh: ChunkSectionMesh, random: Random, neighbours: Array<BlockState?>, light: Int, ambientLight: FloatArray)
|
||||
|
||||
// ToDo: Get ambient light
|
||||
fun getLight(position: Vec3i, random: Random, side: Directions, lightAccessor: LightAccessor): Int
|
||||
|
@ -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<Array<BakedFace>>,
|
||||
val sizes: Array<Array<FaceSize>>,
|
||||
) : 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<BlockState?>, light: Int, ambientLight: IntArray) {
|
||||
override fun getSize(random: Random, direction: Directions): Array<FaceSize> {
|
||||
return sizes[direction.ordinal]
|
||||
}
|
||||
|
||||
override fun singleRender(position: Vec3i, mesh: ChunkSectionMesh, random: Random, neighbours: Array<BlockState?>, 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<FaceSize>? = 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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<MutableList<BakedFace>> = Array(Directions.SIZE) { mutableListOf() }
|
||||
val sizes: Array<MutableList<FaceSize>> = 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<Array<BakedFace>?> = arrayOfNulls(faces.size)
|
||||
|
||||
for ((index, faceArray) in faces.withIndex()) {
|
||||
finalFaces[index] = faceArray.toTypedArray()
|
||||
finalFaces[index] = faceArray.reversed().toTypedArray()
|
||||
}
|
||||
val finalSizes: Array<Array<FaceSize>?> = 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
|
||||
}
|
||||
|
@ -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<UnbakedBlockStateModel>,
|
||||
@ -13,12 +16,25 @@ class UnbakedMultipartModel(
|
||||
|
||||
override fun bake(renderWindow: RenderWindow): BakedModel {
|
||||
val baked: Array<BakedBlockModel?> = arrayOfNulls(this.models.size)
|
||||
val sizes: Array<MutableList<FaceSize>> = 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<Array<FaceSize>?> = 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)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user