minor general performance improvements

This commit is contained in:
Bixilon 2022-09-26 18:35:19 +02:00
parent 2c76371578
commit 61e4b4534d
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
16 changed files with 130 additions and 63 deletions

View File

@ -463,14 +463,17 @@ class Chunk(
sectionLoop@ for (sectionIndex in startY.sectionHeight downTo 0) {
val section = sections[sectionIndex] ?: continue
section.acquire()
for (sectionY in ProtocolDefinition.SECTION_MAX_Y downTo 0) {
val light = section.blocks[x, sectionY, z]?.lightProperties ?: continue
val light = section.blocks.unsafeGet(x, sectionY, z)?.lightProperties ?: continue
if (light.propagatesSkylight) {
continue
}
y = (sectionIndex + lowestSection) * ProtocolDefinition.SECTION_HEIGHT_Y + sectionY
section.release()
break@sectionLoop
}
section.release()
}
skylightHeightmap[(z shl 4) or x] = y
}

View File

@ -109,7 +109,6 @@ class BlockSectionDataProvider(
private fun floodFill(): ShortArray {
// mark regions and check direct neighbours
val regions = ShortArray(ProtocolDefinition.BLOCKS_PER_SECTION)
var nextFloodId = 1.toShort()
fun trace(x: Int, y: Int, z: Int, nextId: Short) {
val index = y shl 8 or (z shl 4) or x
@ -119,9 +118,6 @@ class BlockSectionDataProvider(
}
val blockState = unsafeGet(index)
if (blockState.isSolid()) {
if (nextId == nextFloodId) {
nextFloodId++
}
return
}
regions[index] = nextId
@ -133,10 +129,11 @@ class BlockSectionDataProvider(
if (z < ProtocolDefinition.SECTION_MAX_Z) trace(x, y, z + 1, nextId)
}
var nextFloodId = 1.toShort()
for (y in 0 until ProtocolDefinition.SECTION_HEIGHT_Y) {
for (z in 0 until ProtocolDefinition.SECTION_WIDTH_Z) {
for (x in 0 until ProtocolDefinition.SECTION_WIDTH_X) {
trace(x, y, z, nextFloodId)
trace(x, y, z, nextFloodId++)
}
}
}

View File

@ -0,0 +1,27 @@
/*
* Minosoft
* Copyright (C) 2020-2022 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.data.world.positions
object BlockPositionUtil {
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
}
inline val BlockPosition.positionHash: Long
get() = generatePositionHash(x, y, z)
}

View File

@ -20,10 +20,10 @@ import de.bixilon.minosoft.data.abilities.Gamemodes
import de.bixilon.minosoft.data.registries.blocks.BlockState
import de.bixilon.minosoft.data.registries.blocks.types.FluidBlock
import de.bixilon.minosoft.data.text.formatting.color.RGBColor
import de.bixilon.minosoft.data.world.positions.BlockPositionUtil.positionHash
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.framebuffer.world.overlay.OverlayFactory
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
import de.bixilon.minosoft.gui.rendering.util.VecUtil
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.blockPosition
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.EMPTY
import java.util.*
@ -58,7 +58,7 @@ class WallOverlay(renderWindow: RenderWindow, z: Float) : SimpleOverlay(renderWi
}
override fun draw() {
random.setSeed(VecUtil.generatePositionHash(position.x, position.y, position.z))
random.setSeed(position.positionHash)
texture = blockState?.blockModel?.getParticleTexture(random, position) ?: return
tintColor = RGBColor(0.1f, 0.1f, 0.1f, 1.0f)

View File

@ -17,10 +17,10 @@ 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.BlockState
import de.bixilon.minosoft.data.world.positions.BlockPositionUtil.positionHash
import de.bixilon.minosoft.gui.rendering.models.baked.block.BakedBlockModel
import de.bixilon.minosoft.gui.rendering.models.properties.AbstractFaceProperties
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
import de.bixilon.minosoft.gui.rendering.util.VecUtil
import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh
import java.util.*
import kotlin.math.abs
@ -64,7 +64,7 @@ class WeightedBakedModel(
}
override fun getParticleTexture(random: Random, blockPosition: Vec3i): AbstractTexture? {
random.setSeed(VecUtil.generatePositionHash(blockPosition.x, blockPosition.y, blockPosition.z))
random.setSeed(blockPosition.positionHash)
return getModel(random)?.getParticleTexture(random, blockPosition)
}
}

View File

@ -16,14 +16,16 @@ package de.bixilon.minosoft.gui.rendering.models.baked.block
import de.bixilon.kotlinglm.vec3.Vec3i
import de.bixilon.minosoft.data.direction.Directions
import de.bixilon.minosoft.data.registries.blocks.BlockState
import de.bixilon.minosoft.data.world.positions.BlockPositionUtil
import de.bixilon.minosoft.gui.rendering.models.CullUtil.canCull
import de.bixilon.minosoft.gui.rendering.models.properties.AbstractFaceProperties
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
import de.bixilon.minosoft.gui.rendering.util.VecUtil
import de.bixilon.minosoft.gui.rendering.tint.TintManager
import de.bixilon.minosoft.gui.rendering.util.VecUtil.getWorldOffset
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.toVec3
import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh
import de.bixilon.minosoft.gui.rendering.world.preparer.cull.SolidCullSectionPreparer
import de.bixilon.minosoft.util.KUtil.getOrElse
import java.util.*
class BakedBlockStateModel(
@ -54,7 +56,7 @@ class BakedBlockStateModel(
val neighboursModel = neighbour?.blockModel
var neighbourProperties: Array<AbstractFaceProperties>? = null
if (neighboursModel != null) {
random.setSeed(VecUtil.generatePositionHash(position.x + direction.vector.x, position.y + direction.vector.y, position.z + direction.vector.z))
random.setSeed(BlockPositionUtil.generatePositionHash(position.x + direction.vector.x, position.y + direction.vector.y, position.z + direction.vector.z))
neighbourProperties = neighboursModel.getTouchingFaceProperties(random, direction.inverted)
}
for (face in faces) {
@ -66,7 +68,7 @@ class BakedBlockStateModel(
continue
}
}
tint = tints?.getOrNull(face.tintIndex) ?: -1
tint = tints?.getOrElse(face.tintIndex, TintManager.DEFAULT_TINT_INDEX) ?: TintManager.DEFAULT_TINT_INDEX
currentLight = (face.cullFace?.let { light[it.ordinal] } ?: light[SolidCullSectionPreparer.SELF_LIGHT_INDEX]).toInt()
face.singleRender(positionArray, mesh, currentLight, tint)
if (!rendered) {

View File

@ -17,6 +17,7 @@ import de.bixilon.kotlinglm.vec2.Vec2
import de.bixilon.kutil.primitive.IntUtil.toInt
import de.bixilon.minosoft.data.direction.Directions
import de.bixilon.minosoft.gui.rendering.models.unbaked.element.UnbakedElement.Companion.BLOCK_RESOLUTION
import de.bixilon.minosoft.gui.rendering.tint.TintManager
import de.bixilon.minosoft.util.nbt.tag.NBTUtil.listCast
data class UnbakedElementFace(
@ -48,7 +49,7 @@ data class UnbakedElementFace(
texture = data["texture"].toString(),
cullFace = cullFace,
rotation = data["rotation"]?.toInt() ?: 0,
tintIndex = data["tintindex"]?.toInt() ?: -1,
tintIndex = data["tintindex"]?.toInt() ?: TintManager.DEFAULT_TINT_INDEX,
)
}
}

View File

@ -107,6 +107,7 @@ class TintManager(private val connection: PlayConnection) {
}
companion object {
const val DEFAULT_TINT_INDEX = -1
fun getJsonColor(color: Int): RGBColor? {
if (color == 0) {

View File

@ -26,6 +26,7 @@ import de.bixilon.minosoft.data.direction.Directions
import de.bixilon.minosoft.data.registries.AABB
import de.bixilon.minosoft.data.registries.blocks.RandomOffsetTypes
import de.bixilon.minosoft.data.registries.blocks.types.Block
import de.bixilon.minosoft.data.world.positions.BlockPositionUtil
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.get
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
@ -191,7 +192,7 @@ object VecUtil {
return Vec3.EMPTY
}
val positionHash = generatePositionHash(x, 0, z)
val positionHash = BlockPositionUtil.generatePositionHash(x, 0, z)
val maxModelOffset = 0.25f // ToDo: PixLyzer: use block.model.max_model_offset
fun horizontal(axisHash: Long): Float {
@ -230,12 +231,6 @@ object VecUtil {
val Vec3d.empty: Boolean
get() = this.length() < 0.001
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
}
fun getDistanceToNextIntegerAxisInDirection(position: Vec3d, direction: Vec3d): Double {
fun getTarget(direction: Vec3d, position: Vec3d, axis: Axes): Int {
return if (direction[axis] > 0) {

View File

@ -34,7 +34,7 @@ abstract class Mesh(
private var _data: DirectArrayFloatList? = data ?: if (onDemand) null else DirectArrayFloatList(initialCacheSize)
var data: DirectArrayFloatList
get() {
if (onDemand && _data == null) {
if (_data == null && onDemand) {
_data = DirectArrayFloatList(initialCacheSize)
}
return _data as DirectArrayFloatList

View File

@ -30,13 +30,13 @@ import de.bixilon.minosoft.data.registries.fluid.Fluid
import de.bixilon.minosoft.data.text.formatting.color.Colors
import de.bixilon.minosoft.data.world.chunk.Chunk
import de.bixilon.minosoft.data.world.chunk.ChunkSection
import de.bixilon.minosoft.data.world.positions.BlockPositionUtil.positionHash
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.models.CullUtil.canCull
import de.bixilon.minosoft.gui.rendering.models.properties.FaceProperties
import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureTransparencies
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.util.VecUtil
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.vec3.Vec3Util.rotate
@ -96,7 +96,7 @@ class FluidCullSectionPreparer(
return true
}
val model = neighbour.blockModel ?: return false
random.setSeed(VecUtil.generatePositionHash(neighbourPosition.x, neighbourPosition.y, neighbourPosition.z))
random.setSeed(neighbourPosition.positionHash)
val size = model.getTouchingFaceProperties(random, direction.inverted)
return size?.canCull(FLUID_FACE_PROPERTY, false) ?: false
}

View File

@ -31,9 +31,10 @@ import de.bixilon.minosoft.data.world.chunk.Chunk
import de.bixilon.minosoft.data.world.chunk.ChunkSection
import de.bixilon.minosoft.data.world.chunk.light.SectionLight
import de.bixilon.minosoft.data.world.container.BlockSectionDataProvider
import de.bixilon.minosoft.data.world.positions.BlockPosition
import de.bixilon.minosoft.data.world.positions.BlockPositionUtil.positionHash
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.models.SingleBlockRenderable
import de.bixilon.minosoft.gui.rendering.util.VecUtil
import de.bixilon.minosoft.gui.rendering.world.entities.BlockEntityRenderer
import de.bixilon.minosoft.gui.rendering.world.entities.MeshedBlockEntityRenderer
import de.bixilon.minosoft.gui.rendering.world.entities.OnlyMeshedBlockEntityRenderer
@ -68,7 +69,7 @@ class SolidCullSectionPreparer(
var blockEntity: BlockEntity?
var model: SingleBlockRenderable
var blockState: BlockState
var position: Vec3i
val position = BlockPosition()
var rendered: Boolean
var tints: IntArray?
val neighbourBlocks: Array<BlockState?> = arrayOfNulls(Directions.SIZE)
@ -79,8 +80,10 @@ class SolidCullSectionPreparer(
val offsetZ = chunkPosition.y * ProtocolDefinition.SECTION_WIDTH_Z
for (y in 0 until ProtocolDefinition.SECTION_HEIGHT_Y) {
position.y = offsetY + y
val fastBedrock = y == 0 && isLowestSection && fastBedrock
for (x in 0 until ProtocolDefinition.SECTION_WIDTH_X) {
position.x = offsetX + x
for (z in 0 until ProtocolDefinition.SECTION_WIDTH_Z) {
val baseIndex = (z shl 4) or x
val index = (y shl 8) or baseIndex
@ -89,7 +92,7 @@ class SolidCullSectionPreparer(
continue
}
light[SELF_LIGHT_INDEX] = sectionLight[index]
position = Vec3i(offsetX + x, offsetY + y, offsetZ + z)
position.z = offsetZ + z
val maxHeight = chunk.skylightHeightmap[baseIndex]
if (position.y >= maxHeight) {
@ -152,7 +155,7 @@ class SolidCullSectionPreparer(
}
if (randomBlockModels) {
random.setSeed(VecUtil.generatePositionHash(position.x, position.y, position.z))
random.setSeed(position.positionHash)
} else {
random.setSeed(0L)
}
@ -205,11 +208,11 @@ class SolidCullSectionPreparer(
}
private inline fun setNeighbour(neighbourBlocks: Array<BlockState?>, x: Int, y: Int, z: Int, light: ByteArray, position: Vec3i, blocks: BlockSectionDataProvider?, sectionLight: SectionLight, chunk: Chunk, ordinal: Int) {
val nextBaseIndex = (z shl 4) or x
val neighbourIndex = y shl 8 or nextBaseIndex
val heightmapIndex = (z shl 4) or x
val neighbourIndex = y shl 8 or heightmapIndex
neighbourBlocks[ordinal] = blocks?.unsafeGet(neighbourIndex)
light[ordinal] = sectionLight[neighbourIndex]
if (position.y > chunk.skylightHeightmap[nextBaseIndex]) {
if (position.y > chunk.skylightHeightmap[heightmapIndex]) {
light[ordinal] = (light[ordinal].toInt() or 0xF0).toByte()
}
}

View File

@ -322,4 +322,11 @@ object KUtil {
this[index] = value
return true
}
inline fun IntArray.getOrElse(index: Int, `else`: Int): Int {
if (index < 0 || index >= this.size) {
return `else`
}
return this[index]
}
}

View File

@ -1,15 +1,15 @@
/*
* 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.
*/
* Minosoft
* Copyright (C) 2020-2022 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.util.collections.bytes
class HeapArrayByteList(
@ -53,22 +53,30 @@ class HeapArrayByteList(
while (newSize - size < needed) {
newSize += nextGrowStep
}
grow(newSize)
}
private fun grow(size: Int) {
val oldData = data
data = ByteArray(newSize)
data = ByteArray(size)
System.arraycopy(oldData, 0, data, 0, oldData.size)
}
override fun add(value: Byte) {
ensureSize(1)
data[size++] = value
outputUpToDate = false
if (outputUpToDate) {
outputUpToDate = false
}
}
override fun addAll(bytes: ByteArray) {
ensureSize(bytes.size)
System.arraycopy(bytes, 0, data, size, bytes.size)
size += bytes.size
outputUpToDate = false
if (outputUpToDate) {
outputUpToDate = false
}
}
override fun addAll(byteList: AbstractByteList) {
@ -84,6 +92,10 @@ class HeapArrayByteList(
}
System.arraycopy(source, 0, data, size, byteList.size)
size += byteList.size
if (outputUpToDate) {
outputUpToDate = false
}
}
private fun checkOutputArray() {

View File

@ -52,9 +52,13 @@ class DirectArrayFloatList(
} else {
nextGrowStep
}
grow(newSize)
}
private fun grow(size: Int) {
val oldBuffer = buffer
buffer = memAllocFloat(newSize)
limit = newSize
buffer = memAllocFloat(size)
limit = size
if (FLOAT_PUT_METHOD == null) { // Java < 16
for (i in 0 until oldBuffer.position()) {
buffer.put(oldBuffer.get(i))
@ -69,7 +73,9 @@ class DirectArrayFloatList(
override fun add(value: Float) {
ensureSize(1)
buffer.put(value)
outputUpToDate = false
if (outputUpToDate) {
outputUpToDate = false
}
}
override fun addAll(floats: FloatArray) {
@ -81,7 +87,9 @@ class DirectArrayFloatList(
exception.printStackTrace()
}
outputUpToDate = false
if (outputUpToDate) {
outputUpToDate = false
}
}
override fun addAll(floatList: AbstractFloatList) {

View File

@ -1,15 +1,15 @@
/*
* 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.
*/
* Minosoft
* Copyright (C) 2020-2022 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.util.collections.floats
class HeapArrayFloatList(
@ -53,22 +53,30 @@ class HeapArrayFloatList(
while (newSize - size < needed) {
newSize += nextGrowStep
}
grow(newSize)
}
private fun grow(size: Int) {
val oldData = data
data = FloatArray(newSize)
data = FloatArray(size)
System.arraycopy(oldData, 0, data, 0, oldData.size)
}
override fun add(value: Float) {
ensureSize(1)
data[size++] = value
outputUpToDate = false
if (outputUpToDate) {
outputUpToDate = false
}
}
override fun addAll(floats: FloatArray) {
ensureSize(floats.size)
System.arraycopy(floats, 0, data, size, floats.size)
size += floats.size
outputUpToDate = false
if (outputUpToDate) {
outputUpToDate = false
}
}
override fun addAll(floatList: AbstractFloatList) {
@ -84,6 +92,9 @@ class HeapArrayFloatList(
}
System.arraycopy(source, 0, data, size, floatList.size)
size += floatList.size
if (outputUpToDate) {
outputUpToDate = false
}
}
private fun checkOutputArray() {