mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-11 16:36:58 -04:00
normal cull section preparer
This commit is contained in:
parent
2455359747
commit
2279af73a1
@ -101,6 +101,7 @@ enum class Directions(
|
||||
|
||||
|
||||
companion object : BlockPropertiesSerializer, ValuesEnum<Directions> {
|
||||
const val SIZE = 6
|
||||
override val VALUES = values()
|
||||
override val NAME_MAP: Map<String, Directions> = KUtil.getEnumValues(VALUES)
|
||||
val SIDES = arrayOf(NORTH, SOUTH, WEST, EAST)
|
||||
|
@ -24,6 +24,10 @@ import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.Renderer
|
||||
import de.bixilon.minosoft.gui.rendering.RendererBuilder
|
||||
import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMesh
|
||||
import de.bixilon.minosoft.gui.rendering.block.preparer.AbstractSectionPreparer
|
||||
import de.bixilon.minosoft.gui.rendering.block.preparer.CullSectionPreparer
|
||||
import de.bixilon.minosoft.gui.rendering.block.preparer.GenericSectionPreparer
|
||||
import de.bixilon.minosoft.gui.rendering.block.preparer.GreedySectionPreparer
|
||||
import de.bixilon.minosoft.gui.rendering.models.ModelLoader
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.RenderSystem
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.phases.OpaqueDrawable
|
||||
@ -43,10 +47,13 @@ class WorldRenderer(
|
||||
override val renderSystem: RenderSystem = renderWindow.renderSystem
|
||||
private val shader = renderSystem.createShader("minosoft:world".toResourceLocation())
|
||||
private val world: World = connection.world
|
||||
private val sectionPreparer = SectionPreparer(renderWindow)
|
||||
private val sectionPreparer: AbstractSectionPreparer = GenericSectionPreparer(renderWindow)
|
||||
private val lightMap = LightMap(connection)
|
||||
private lateinit var mesh: ChunkSectionMesh
|
||||
|
||||
private val culledPreparer = GenericSectionPreparer(renderWindow, CullSectionPreparer(renderWindow))
|
||||
private val greedyPreparer = GenericSectionPreparer(renderWindow, GreedySectionPreparer(renderWindow))
|
||||
|
||||
|
||||
override fun init() {
|
||||
val asset = Resources.getAssetVersionByVersion(connection.version)
|
||||
@ -66,9 +73,24 @@ class WorldRenderer(
|
||||
|
||||
val random = Random(0L)
|
||||
val blockState = connection.registries.blockRegistry["diamond_block"]?.defaultState
|
||||
val chunk = ChunkSection(Array(4096) { if (random.nextBoolean()) blockState else null })
|
||||
val section = ChunkSection(Array(4096) { if (random.nextBoolean()) blockState else null })
|
||||
|
||||
mesh = sectionPreparer.prepare(section)
|
||||
/*
|
||||
for (i in 0 until 1000)
|
||||
mesh = sectionPreparer.prepare(chunk)
|
||||
mesh = sectionPreparer.prepare(section)
|
||||
|
||||
Log.log(LogMessageType.OTHER, LogLevels.WARN){"Culling now..."}
|
||||
|
||||
val culledMesh = culledPreparer.prepare(section)
|
||||
for (i in 0 until 1000){
|
||||
culledPreparer.prepare(section)
|
||||
}
|
||||
val greedyMesh = greedyPreparer.prepare(section)
|
||||
|
||||
Log.log(LogMessageType.OTHER,LogLevels.INFO){"Culling has ${culledMesh.data.size / ChunkSectionMesh.SectionArrayMeshStruct.FLOATS_PER_VERTEX}, greedy meshed has ${greedyMesh.data.size / ChunkSectionMesh.SectionArrayMeshStruct.FLOATS_PER_VERTEX}."}
|
||||
|
||||
*/
|
||||
mesh.load()
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,10 @@
|
||||
package de.bixilon.minosoft.gui.rendering.block.preparer
|
||||
|
||||
import de.bixilon.minosoft.data.world.ChunkSection
|
||||
import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMesh
|
||||
|
||||
interface AbstractSectionPreparer {
|
||||
|
||||
fun prepare(section: ChunkSection): ChunkSectionMesh
|
||||
|
||||
}
|
@ -0,0 +1,70 @@
|
||||
package de.bixilon.minosoft.gui.rendering.block.preparer
|
||||
|
||||
import de.bixilon.minosoft.data.direction.Directions
|
||||
import de.bixilon.minosoft.data.registries.blocks.BlockState
|
||||
import de.bixilon.minosoft.data.world.ChunkSection
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMesh
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
import glm_.vec3.Vec3i
|
||||
import java.util.*
|
||||
|
||||
class CullSectionPreparer(
|
||||
val renderWindow: RenderWindow,
|
||||
) : AbstractSectionPreparer {
|
||||
|
||||
override fun prepare(section: ChunkSection): ChunkSectionMesh {
|
||||
val mesh = ChunkSectionMesh(renderWindow)
|
||||
val random = Random(0L)
|
||||
|
||||
var block: BlockState?
|
||||
val neighbours: Array<BlockState?> = arrayOfNulls(Directions.SIZE)
|
||||
|
||||
for (x in 0 until ProtocolDefinition.SECTION_WIDTH_X) {
|
||||
for (y in 0 until ProtocolDefinition.SECTION_HEIGHT_Y) {
|
||||
for (z in 0 until ProtocolDefinition.SECTION_WIDTH_Z) {
|
||||
block = section.blocks[ChunkSection.getIndex(x, y, z)]
|
||||
|
||||
// ToDo: Chunk borders
|
||||
neighbours[Directions.DOWN.ordinal] = if (y == 0) {
|
||||
null
|
||||
} else {
|
||||
section.blocks[ChunkSection.getIndex(x, y - 1, z)]
|
||||
}
|
||||
neighbours[Directions.UP.ordinal] = if (y == ProtocolDefinition.SECTION_MAX_Y) {
|
||||
null
|
||||
} else {
|
||||
section.blocks[ChunkSection.getIndex(x, y + 1, z)]
|
||||
}
|
||||
neighbours[Directions.NORTH.ordinal] = if (z == 0) {
|
||||
null
|
||||
} else {
|
||||
section.blocks[ChunkSection.getIndex(x, y, z - 1)]
|
||||
}
|
||||
neighbours[Directions.SOUTH.ordinal] = if (z == ProtocolDefinition.SECTION_MAX_Z) {
|
||||
null
|
||||
} else {
|
||||
section.blocks[ChunkSection.getIndex(x, y, z + 1)]
|
||||
}
|
||||
neighbours[Directions.WEST.ordinal] = if (x == 0) {
|
||||
null
|
||||
} else {
|
||||
section.blocks[ChunkSection.getIndex(x - 1, y, z)]
|
||||
}
|
||||
neighbours[Directions.EAST.ordinal] = if (x == ProtocolDefinition.SECTION_MAX_X) {
|
||||
null
|
||||
} else {
|
||||
section.blocks[ChunkSection.getIndex(x + 1, y, z)]
|
||||
}
|
||||
|
||||
random.setSeed(VecUtil.generatePositionHash(x, y, z))
|
||||
block?.model?.singleRender(Vec3i(x, y, z), mesh, random, neighbours, 0xFF, intArrayOf(0xF, 0xF, 0xF, 0xF))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return mesh
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2021 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.block.preparer
|
||||
|
||||
import de.bixilon.minosoft.data.world.ChunkSection
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMesh
|
||||
import de.bixilon.minosoft.util.logging.Log
|
||||
import de.bixilon.minosoft.util.logging.LogLevels
|
||||
import de.bixilon.minosoft.util.logging.LogMessageType
|
||||
|
||||
|
||||
class GenericSectionPreparer(
|
||||
val renderWindow: RenderWindow,
|
||||
private val preparer: AbstractSectionPreparer = GreedySectionPreparer(renderWindow),
|
||||
) : AbstractSectionPreparer {
|
||||
|
||||
override fun prepare(section: ChunkSection): ChunkSectionMesh {
|
||||
val startTime = System.nanoTime()
|
||||
|
||||
val mesh = preparer.prepare(section)
|
||||
|
||||
val time = System.nanoTime()
|
||||
val delta = time - startTime
|
||||
Log.log(LogMessageType.OTHER, LogLevels.VERBOSE) { "Preparing took ${delta}ns, ${delta / 1000}µs, ${delta / 1000000}ms" }
|
||||
|
||||
return mesh
|
||||
}
|
||||
}
|
@ -11,37 +11,38 @@
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.gui.rendering.block
|
||||
package de.bixilon.minosoft.gui.rendering.block.preparer
|
||||
|
||||
import de.bixilon.minosoft.data.direction.Directions
|
||||
import de.bixilon.minosoft.data.registries.blocks.BlockState
|
||||
import de.bixilon.minosoft.data.world.ChunkSection
|
||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||
import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMesh
|
||||
import de.bixilon.minosoft.gui.rendering.models.baked.block.GreedyBakedBlockModel
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition.SECTION_SIZE
|
||||
import de.bixilon.minosoft.util.KUtil.decide
|
||||
import de.bixilon.minosoft.util.logging.Log
|
||||
import de.bixilon.minosoft.util.logging.LogLevels
|
||||
import de.bixilon.minosoft.util.logging.LogMessageType
|
||||
import glm_.vec3.Vec3i
|
||||
import java.util.*
|
||||
|
||||
|
||||
class SectionPreparer(
|
||||
class GreedySectionPreparer(
|
||||
val renderWindow: RenderWindow,
|
||||
) {
|
||||
) : AbstractSectionPreparer {
|
||||
|
||||
private fun renderNormal(position: Vec3i, section: ChunkSection, mesh: ChunkSectionMesh, random: Random) {
|
||||
// ToDo
|
||||
}
|
||||
|
||||
|
||||
fun prepare(section: ChunkSection): ChunkSectionMesh {
|
||||
val startTime = System.nanoTime()
|
||||
override fun prepare(section: ChunkSection): ChunkSectionMesh {
|
||||
val mesh = ChunkSectionMesh(renderWindow)
|
||||
|
||||
val random = Random(0L)
|
||||
|
||||
var currentBlock: BlockState?
|
||||
var compareBlock: BlockState?
|
||||
var start: Vec3i
|
||||
var end: Vec3i
|
||||
|
||||
for (direction in Directions.VALUES) {
|
||||
// Sweep over each axis (X, Y and Z)
|
||||
@ -80,8 +81,8 @@ class SectionPreparer(
|
||||
n++
|
||||
continue
|
||||
}
|
||||
val currentBlock = if (position[axis] >= 0) section.blocks[ChunkSection.getIndex(position[0], position[1], position[2])] else null
|
||||
val compareBlock = if (position[axis] < SECTION_SIZE - 1) section.blocks[ChunkSection.getIndex(position[0] + checkOffset[0], position[1] + checkOffset[1], position[2] + checkOffset[2])] else null
|
||||
currentBlock = if (position[axis] >= 0) section.blocks[ChunkSection.getIndex(position[0], position[1], position[2])] else null
|
||||
compareBlock = if (position[axis] < SECTION_SIZE - 1) section.blocks[ChunkSection.getIndex(position[0] + checkOffset[0], position[1] + checkOffset[1], position[2] + checkOffset[2])] else null
|
||||
|
||||
// The mask is set to true if there is a visible face between two blocks,
|
||||
// i.e. both aren't empty and both aren't blocks
|
||||
@ -150,14 +151,14 @@ class SectionPreparer(
|
||||
position[axis] -= offsetCheck
|
||||
}
|
||||
|
||||
val start = Vec3i(position[0], position[1], position[2])
|
||||
start = Vec3i(position[0], position[1], position[2])
|
||||
|
||||
|
||||
val end = Vec3i(position[0] + du[0] + dv[0], position[1] + du[1] + dv[1], position[2] + du[2] + dv[2])
|
||||
end = Vec3i(position[0] + du[0] + dv[0], position[1] + du[1] + dv[1], position[2] + du[2] + dv[2])
|
||||
|
||||
|
||||
val block = section.blocks[ChunkSection.getIndex(position[0], position[1], position[2])]!!
|
||||
(block.model as GreedyBakedBlockModel).greedyRender(start, end, direction, mesh, 0xFF)
|
||||
currentBlock = section.blocks[ChunkSection.getIndex(position[0], position[1], position[2])]!!
|
||||
(currentBlock.model as GreedyBakedBlockModel).greedyRender(start, end, direction, mesh, 0xFF)
|
||||
|
||||
|
||||
if (!backFace) {
|
||||
@ -188,11 +189,6 @@ class SectionPreparer(
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
val time = System.nanoTime()
|
||||
val delta = time - startTime
|
||||
Log.log(LogMessageType.OTHER, LogLevels.VERBOSE) { "Preparing took ${delta}ns, ${delta / 1000}µs, ${delta / 1000000}ms" }
|
||||
|
||||
return mesh
|
||||
}
|
||||
}
|
@ -68,7 +68,7 @@ data class UnbakedBlockStateModel(
|
||||
}
|
||||
|
||||
|
||||
val faces: Array<MutableList<BakedFace>> = Array(Directions.VALUES.size) { mutableListOf() }
|
||||
val faces: Array<MutableList<BakedFace>> = Array(Directions.SIZE) { mutableListOf() }
|
||||
|
||||
for (element in model.elements) {
|
||||
val rescale = element.rotation?.rescale ?: false
|
||||
|
@ -279,7 +279,7 @@ object VecUtil {
|
||||
val Vec3d.empty: Boolean
|
||||
get() = this.length() < 0.001
|
||||
|
||||
private fun generatePositionHash(x: Int, y: Int, z: Int): Long {
|
||||
fun generatePositionHash(x: Int, y: Int, z: Int): Long {
|
||||
var hash = (x * 3129871L) xor z.toLong() * 116129781L xor y.toLong()
|
||||
hash = hash * hash * 42317861L + hash * 11L
|
||||
return hash shr 16
|
||||
|
Loading…
x
Reference in New Issue
Block a user