mesher: improve (fluid) perpare speed

This commit is contained in:
Bixilon 2022-05-04 19:45:00 +02:00
parent cea55b610a
commit 971ed120cf
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
12 changed files with 51 additions and 31 deletions

View File

@ -147,7 +147,7 @@ data class BlockState(
fallSoundEvent = data["fall_sound_type"]?.toInt()?.let { registries.soundEventRegistry[it] }, fallSoundEvent = data["fall_sound_type"]?.toInt()?.let { registries.soundEventRegistry[it] },
soundEventVolume = data["sound_type_volume"]?.toFloat() ?: 1.0f, soundEventVolume = data["sound_type_volume"]?.toFloat() ?: 1.0f,
soundEventPitch = data["sound_type_pitch"]?.toFloat() ?: 1.0f, soundEventPitch = data["sound_type_pitch"]?.toFloat() ?: 1.0f,
isSolid = data["solid_render"]?.toBoolean() ?: true, // ToDo: This should normally be false, but pixlyzers default value is true. Might break if the data is missing isSolid = data["solid_render"]?.toBoolean() ?: false,
) )
} }

View File

@ -73,7 +73,7 @@ class Chunk(
operator fun get(position: Vec3i): BlockState? = get(position.x, position.y, position.z) operator fun get(position: Vec3i): BlockState? = get(position.x, position.y, position.z)
fun set(x: Int, y: Int, z: Int, blockState: BlockState?, blockEntity: BlockEntity? = null) { fun set(x: Int, y: Int, z: Int, blockState: BlockState?, blockEntity: BlockEntity? = null) {
val section = getOrPut(y.sectionHeight) val section = getOrPut(y.sectionHeight) ?: return
section.blocks[x, y.inSectionHeight, z] = blockState section.blocks[x, y.inSectionHeight, z] = blockState
section.blockEntities[x, y.inSectionHeight, z] = blockEntity // ToDo section.blockEntities[x, y.inSectionHeight, z] = blockEntity // ToDo
} }
@ -103,7 +103,7 @@ class Chunk(
return null return null
} }
blockEntity = block.block.factory?.build(connection) ?: return null blockEntity = block.block.factory?.build(connection) ?: return null
this.getOrPut(sectionHeight).blockEntities[x, inSectionHeight, z] = blockEntity (this.getOrPut(sectionHeight) ?: return null).blockEntities[x, inSectionHeight, z] = blockEntity
return blockEntity return blockEntity
} }
@ -112,7 +112,7 @@ class Chunk(
fun getOrPutBlockEntity(position: Vec3i): BlockEntity? = getOrPutBlockEntity(position.x, position.y, position.z) fun getOrPutBlockEntity(position: Vec3i): BlockEntity? = getOrPutBlockEntity(position.x, position.y, position.z)
fun setBlockEntity(x: Int, y: Int, z: Int, blockEntity: BlockEntity?) { fun setBlockEntity(x: Int, y: Int, z: Int, blockEntity: BlockEntity?) {
getOrPut(y.sectionHeight).blockEntities[x, y.inSectionHeight, z] = blockEntity (getOrPut(y.sectionHeight) ?: return).blockEntities[x, y.inSectionHeight, z] = blockEntity
} }
fun setBlockEntity(position: Vec3i, blockEntity: BlockEntity?) = setBlockEntity(position.x, position.y, position.z, blockEntity) fun setBlockEntity(position: Vec3i, blockEntity: BlockEntity?) = setBlockEntity(position.x, position.y, position.z, blockEntity)
@ -133,7 +133,7 @@ class Chunk(
data.blocks?.let { data.blocks?.let {
for ((index, blocks) in it.withIndex()) { for ((index, blocks) in it.withIndex()) {
blocks ?: continue blocks ?: continue
val section = getOrPut(index + lowestSection) val section = getOrPut(index + lowestSection) ?: return@let
section.blocks = blocks section.blocks = blocks
} }
blocksInitialized = true blocksInitialized = true
@ -146,7 +146,7 @@ class Chunk(
data.light?.let { data.light?.let {
for ((index, light) in it.withIndex()) { for ((index, light) in it.withIndex()) {
light ?: continue light ?: continue
val section = getOrPut(index + lowestSection) val section = getOrPut(index + lowestSection) ?: return@let
section.light = light section.light = light
} }
lightInitialized = true lightInitialized = true
@ -170,9 +170,12 @@ class Chunk(
} }
@Synchronized @Synchronized
private fun getOrPut(sectionHeight: Int): ChunkSection { private fun getOrPut(sectionHeight: Int): ChunkSection? {
val sections = sections ?: throw NullPointerException("Sections not initialized yet!") val sections = sections ?: throw NullPointerException("Sections not initialized yet!")
val sectionIndex = sectionHeight - lowestSection val sectionIndex = sectionHeight - lowestSection
if (sectionIndex < 0 || sectionIndex > sections.size) {
return null
}
var section = sections[sectionIndex] var section = sections[sectionIndex]
if (section == null) { if (section == null) {

View File

@ -20,5 +20,5 @@ import java.util.*
interface SingleBlockRenderable { interface SingleBlockRenderable {
fun singleRender(position: Vec3i, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array<BlockState?>, light: ByteArray, ambientLight: FloatArray, tints: IntArray?): Boolean fun singleRender(position: Vec3i, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array<BlockState?>, light: ByteArray, tints: IntArray?): Boolean
} }

View File

@ -32,10 +32,10 @@ class MultipartBakedModel(
return sizes[direction.ordinal] return sizes[direction.ordinal]
} }
override fun singleRender(position: Vec3i, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array<BlockState?>, light: ByteArray, ambientLight: FloatArray, tints: IntArray?): Boolean { override fun singleRender(position: Vec3i, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array<BlockState?>, light: ByteArray, tints: IntArray?): Boolean {
var rendered = false var rendered = false
for (model in models) { for (model in models) {
if (model.singleRender(position, mesh, random, blockState, neighbours, light, ambientLight, tints) && !rendered) { if (model.singleRender(position, mesh, random, blockState, neighbours, light, tints) && !rendered) {
rendered = true rendered = true
} }
} }

View File

@ -58,8 +58,8 @@ class WeightedBakedModel(
throw IllegalStateException("Could not find a model: This should never happen!") throw IllegalStateException("Could not find a model: This should never happen!")
} }
override fun singleRender(position: Vec3i, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array<BlockState?>, light: ByteArray, ambientLight: FloatArray, tints: IntArray?): Boolean { override fun singleRender(position: Vec3i, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array<BlockState?>, light: ByteArray, tints: IntArray?): Boolean {
return getModel(random)?.singleRender(position, mesh, random, blockState, neighbours, light, ambientLight, tints) ?: false return getModel(random)?.singleRender(position, mesh, random, blockState, neighbours, light, tints) ?: false
} }
override fun getParticleTexture(random: Random, blockPosition: Vec3i): AbstractTexture? { override fun getParticleTexture(random: Random, blockPosition: Vec3i): AbstractTexture? {

View File

@ -36,7 +36,7 @@ class BakedBlockStateModel(
return touchingFaceProperties[direction.ordinal] return touchingFaceProperties[direction.ordinal]
} }
override fun singleRender(position: Vec3i, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array<BlockState?>, light: ByteArray, ambientLight: FloatArray, tints: IntArray?): Boolean { override fun singleRender(position: Vec3i, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array<BlockState?>, light: ByteArray, tints: IntArray?): Boolean {
val floatPosition = position.toVec3() val floatPosition = position.toVec3()
blockState.block.randomOffsetType?.let { blockState.block.randomOffsetType?.let {
floatPosition += position.getWorldOffset(blockState.block) floatPosition += position.getWorldOffset(blockState.block)
@ -68,7 +68,7 @@ class BakedBlockStateModel(
} }
tint = tints?.getOrNull(face.tintIndex) ?: -1 tint = tints?.getOrNull(face.tintIndex) ?: -1
currentLight = (face.cullFace?.let { light[it.ordinal] } ?: light[SolidCullSectionPreparer.SELF_LIGHT_INDEX]).toInt() currentLight = (face.cullFace?.let { light[it.ordinal] } ?: light[SolidCullSectionPreparer.SELF_LIGHT_INDEX]).toInt()
face.singleRender(positionArray, mesh, currentLight, ambientLight, tint) face.singleRender(positionArray, mesh, currentLight, tint)
if (!rendered) { if (!rendered) {
rendered = true rendered = true
} }

View File

@ -38,7 +38,7 @@ class BakedFace(
override val transparency: TextureTransparencies override val transparency: TextureTransparencies
get() = texture.transparency // ToDo get() = texture.transparency // ToDo
fun singleRender(position: FloatArray, mesh: WorldMesh, light: Int, ambientLight: FloatArray, tint: Int) { fun singleRender(position: FloatArray, mesh: WorldMesh, light: Int, tint: Int) {
val meshToUse = transparency.getMesh(mesh) val meshToUse = transparency.getMesh(mesh)
// ToDo: Ambient light // ToDo: Ambient light
val color = Vec3(shade) val color = Vec3(shade)

View File

@ -45,7 +45,7 @@ class SignBlockEntityRenderer(
override val blockState: BlockState, override val blockState: BlockState,
) : OnlyMeshedBlockEntityRenderer<SignBlockEntity> { ) : OnlyMeshedBlockEntityRenderer<SignBlockEntity> {
override fun singleRender(position: Vec3i, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array<BlockState?>, light: ByteArray, ambientLight: FloatArray, tints: IntArray?): Boolean { override fun singleRender(position: Vec3i, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array<BlockState?>, light: ByteArray, tints: IntArray?): Boolean {
val block = this.blockState.block val block = this.blockState.block
if (block is StandingSignBlock) { if (block is StandingSignBlock) {
renderStandingText(position, mesh, light[SolidCullSectionPreparer.SELF_LIGHT_INDEX].toInt()) renderStandingText(position, mesh, light[SolidCullSectionPreparer.SELF_LIGHT_INDEX].toInt())

View File

@ -37,6 +37,8 @@ import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureTransparenci
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.getMesh import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.getMesh
import de.bixilon.minosoft.gui.rendering.util.VecUtil import de.bixilon.minosoft.gui.rendering.util.VecUtil
import de.bixilon.minosoft.gui.rendering.util.VecUtil.chunkPosition
import de.bixilon.minosoft.gui.rendering.util.VecUtil.inChunkPosition
import de.bixilon.minosoft.gui.rendering.util.VecUtil.plus import de.bixilon.minosoft.gui.rendering.util.VecUtil.plus
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2Util.EMPTY import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2Util.EMPTY
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.rotate import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.rotate
@ -128,10 +130,10 @@ class FluidCullSectionPreparer(
} }
val cornerHeights = floatArrayOf( val cornerHeights = floatArrayOf(
getCornerHeight(position, fluid), getCornerHeight(chunk, chunkPosition, position, fluid),
getCornerHeight(position + Directions.EAST, fluid), getCornerHeight(chunk, chunkPosition, position + Directions.EAST, fluid),
getCornerHeight(position + Directions.EAST + Directions.SOUTH, fluid), getCornerHeight(chunk, chunkPosition, position + Directions.EAST + Directions.SOUTH, fluid),
getCornerHeight(position + Directions.SOUTH, fluid), getCornerHeight(chunk, chunkPosition, position + Directions.SOUTH, fluid),
) )
if (!skip[Directions.O_UP]) { if (!skip[Directions.O_UP]) {
@ -262,21 +264,38 @@ class FluidCullSectionPreparer(
neighbours.release() neighbours.release()
} }
private fun getCornerHeight(position: Vec3i, fluid: Fluid): Float { private fun getCornerHeight(providedChunk: Chunk, providedChunkPosition: Vec2i, position: Vec3i, fluid: Fluid): Float {
// ToDo: Optimize // ToDo: Optimize more
var totalHeight = 0.0f var totalHeight = 0.0f
var count = 0 var count = 0
var lastChunkPosition = providedChunkPosition
var lastChunk: Chunk? = providedChunk
for (side in 0 until 4) { for (side in 0 until 4) {
val blockPosition = position + Vec3i(-(side and 0x01), 0, -(side shr 1 and 0x01)) val blockPosition = position + Vec3i(-(side and 0x01), 0, -(side shr 1 and 0x01))
if (fluid.matches(world[blockPosition + Directions.UP])) { val chunkPosition = blockPosition.chunkPosition
if (chunkPosition != lastChunkPosition) {
lastChunkPosition = chunkPosition
lastChunk = world[chunkPosition]
}
if (lastChunk == null) {
count++
continue
}
val inChunkPosition = blockPosition.inChunkPosition
if (fluid.matches(lastChunk[inChunkPosition + Directions.UP])) {
return 1.0f return 1.0f
} }
val blockState = world[blockPosition] val blockState = lastChunk[inChunkPosition]
if (blockState == null) {
count++
continue
}
if (blockState == null || !fluid.matches(blockState)) { if (!fluid.matches(blockState)) {
if (blockState?.material?.solid != true) { if (!blockState.material.solid) {
count++ count++
} }
continue continue

View File

@ -49,7 +49,6 @@ class SolidCullSectionPreparer(
private val bedrock = renderWindow.connection.registries.blockRegistry[MinecraftBlocks.BEDROCK]?.defaultState private val bedrock = renderWindow.connection.registries.blockRegistry[MinecraftBlocks.BEDROCK]?.defaultState
private val someFullBlock = renderWindow.connection.registries.blockRegistry[MinecraftBlocks.COMMAND_BLOCK]?.defaultState private val someFullBlock = renderWindow.connection.registries.blockRegistry[MinecraftBlocks.COMMAND_BLOCK]?.defaultState
private val tintColorCalculator = renderWindow.tintManager private val tintColorCalculator = renderWindow.tintManager
private val ambientLight = floatArrayOf(1.0f, 1.0f, 1.0f, 1.0f)
private var fastBedrock = false private var fastBedrock = false
init { init {
@ -167,10 +166,10 @@ class SolidCullSectionPreparer(
random.setSeed(0L) random.setSeed(0L)
} }
tints = tintColorCalculator.getAverageTint(chunk, neighbourChunks, blockState, x, y, z) tints = tintColorCalculator.getAverageTint(chunk, neighbourChunks, blockState, x, y, z)
rendered = model.singleRender(position, mesh, random, blockState, neighbourBlocks, light, ambientLight, tints) rendered = model.singleRender(position, mesh, random, blockState, neighbourBlocks, light, tints)
if (blockEntityModel is MeshedBlockEntityRenderer<*>) { if (blockEntityModel is MeshedBlockEntityRenderer<*>) {
rendered = blockEntityModel.singleRender(position, mesh, random, blockState, neighbourBlocks, light, ambientLight, tints) || rendered rendered = blockEntityModel.singleRender(position, mesh, random, blockState, neighbourBlocks, light, tints) || rendered
} }
if (rendered) { if (rendered) {

View File

@ -420,7 +420,7 @@ open class InByteBuffer {
return Pair(resourceLocation, Tag(items.toSet())) return Pair(resourceLocation, Tag(items.toSet()))
} }
@Deprecated("Use readArray") @Deprecated("Use readArray", ReplaceWith("mapOf(*(readArray(length) { readTag(idResolver) }))"))
fun <T> readTagArray(length: Int = readVarInt(), idResolver: (Int) -> T): Map<ResourceLocation, Tag<T>> { fun <T> readTagArray(length: Int = readVarInt(), idResolver: (Int) -> T): Map<ResourceLocation, Tag<T>> {
return mapOf(*(readArray(length) { readTag(idResolver) })) return mapOf(*(readArray(length) { readTag(idResolver) }))
} }

View File

@ -217,7 +217,6 @@ class PlayInByteBuffer : InByteBuffer {
return readArray(length) { readEntityId() } return readArray(length) { readEntityId() }
} }
fun readPlayerProperties(): PlayerProperties { fun readPlayerProperties(): PlayerProperties {
var textures: PlayerTextures? = null var textures: PlayerTextures? = null
for (i in 0 until readVarInt()) { for (i in 0 until readVarInt()) {