From 5fc6b606bb5da5eba1b5d5aa2e623a6d9da617bf Mon Sep 17 00:00:00 2001 From: Bixilon Date: Mon, 22 Nov 2021 18:40:21 +0100 Subject: [PATCH] count FluidFillable blocks as fluid, restructure some fluid stuff --- .../registries/blocks/types/FluidFillable.kt | 4 +- .../container/BlockSectionDataProvider.kt | 24 +++++- .../gui/rendering/world/WorldRenderer.kt | 17 ++-- ...ionPreparer.kt => FluidSectionPreparer.kt} | 4 +- .../world/preparer/GreedySectionPreparer.kt | 6 +- .../world/preparer/SolidSectionPreparer.kt | 11 +++ .../preparer/cull/FluidCullSectionPreparer.kt | 78 +++++++++++++++++++ .../SolidCullSectionPreparer.kt} | 59 +------------- 8 files changed, 128 insertions(+), 75 deletions(-) rename src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/{AbstractSectionPreparer.kt => FluidSectionPreparer.kt} (66%) create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/SolidSectionPreparer.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/cull/FluidCullSectionPreparer.kt rename src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/{CullSectionPreparer.kt => cull/SolidCullSectionPreparer.kt} (74%) diff --git a/src/main/java/de/bixilon/minosoft/data/registries/blocks/types/FluidFillable.kt b/src/main/java/de/bixilon/minosoft/data/registries/blocks/types/FluidFillable.kt index c08109b3d..54e88bbcf 100644 --- a/src/main/java/de/bixilon/minosoft/data/registries/blocks/types/FluidFillable.kt +++ b/src/main/java/de/bixilon/minosoft/data/registries/blocks/types/FluidFillable.kt @@ -13,8 +13,8 @@ package de.bixilon.minosoft.data.registries.blocks.types -import de.bixilon.minosoft.data.registries.ResourceLocation +import de.bixilon.minosoft.data.registries.fluid.Fluid interface FluidFillable { - val fluid: ResourceLocation + val fluid: Fluid } diff --git a/src/main/java/de/bixilon/minosoft/data/world/container/BlockSectionDataProvider.kt b/src/main/java/de/bixilon/minosoft/data/world/container/BlockSectionDataProvider.kt index c10448033..ecc3e8d2e 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/container/BlockSectionDataProvider.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/container/BlockSectionDataProvider.kt @@ -1,7 +1,9 @@ package de.bixilon.minosoft.data.world.container import de.bixilon.minosoft.data.registries.blocks.BlockState +import de.bixilon.minosoft.data.registries.blocks.properties.BlockProperties import de.bixilon.minosoft.data.registries.blocks.types.FluidBlock +import de.bixilon.minosoft.data.registries.blocks.types.FluidFillable import de.bixilon.minosoft.util.KUtil.unsafeCast class BlockSectionDataProvider( @@ -16,7 +18,7 @@ class BlockSectionDataProvider( fluidCount = 0 for (blockState in data) { - if (blockState?.block is FluidBlock) { + if (blockState.isFluid()) { fluidCount++ } } @@ -24,13 +26,29 @@ class BlockSectionDataProvider( override fun set(index: Int, value: BlockState?): BlockState? { val previous = super.set(index, value) + val previousFluid = previous.isFluid() + val valueFluid = value.isFluid() - if (previous?.block !is FluidBlock && value?.block is FluidBlock) { + if (!previousFluid && valueFluid) { fluidCount++ - } else if (previous?.block is FluidBlock && value?.block !is FluidBlock) { + } else if (previousFluid && !valueFluid) { fluidCount-- } return previous } + + private fun BlockState?.isFluid(): Boolean { + this ?: return false + if (this.block is FluidBlock) { + return true + } + if (properties[BlockProperties.WATERLOGGED] == true) { + return true + } + if (this.block is FluidFillable) { + return true + } + return false + } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/WorldRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/WorldRenderer.kt index 418f5d74b..98ce3c74f 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/WorldRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/WorldRenderer.kt @@ -49,8 +49,10 @@ import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.toVec3 import de.bixilon.minosoft.gui.rendering.world.mesh.SectionMesh import de.bixilon.minosoft.gui.rendering.world.mesh.VisibleMeshes import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh -import de.bixilon.minosoft.gui.rendering.world.preparer.AbstractSectionPreparer -import de.bixilon.minosoft.gui.rendering.world.preparer.CullSectionPreparer +import de.bixilon.minosoft.gui.rendering.world.preparer.FluidSectionPreparer +import de.bixilon.minosoft.gui.rendering.world.preparer.SolidSectionPreparer +import de.bixilon.minosoft.gui.rendering.world.preparer.cull.FluidCullSectionPreparer +import de.bixilon.minosoft.gui.rendering.world.preparer.cull.SolidCullSectionPreparer import de.bixilon.minosoft.modding.event.events.* import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionStateChangeEvent import de.bixilon.minosoft.modding.event.invoker.CallbackEventInvoker @@ -84,7 +86,8 @@ class WorldRenderer( private val shader = renderSystem.createShader("minosoft:world".toResourceLocation()) private val transparentShader = renderSystem.createShader("minosoft:world".toResourceLocation()) private val world: World = connection.world - private val sectionPreparer: AbstractSectionPreparer = CullSectionPreparer(renderWindow) + private val solidSectionPreparer: SolidSectionPreparer = SolidCullSectionPreparer(renderWindow) + private val fluidSectionPreparer: FluidSectionPreparer = FluidCullSectionPreparer(renderWindow) private val lightMap = LightMap(connection) private val loadedMeshes: MutableMap> = mutableMapOf() // all prepared (and up to date) meshes @@ -106,8 +109,8 @@ class WorldRenderer( // all meshes that will be rendered in the next frame (might be changed, when the frustum changes or a chunk gets loaded, ...) private var clearVisibleNextFrame = false - private var visibleSolid = VisibleMeshes() - private var visibleFluid = VisibleMeshes() + private var visibleSolid = VisibleMeshes() // This name might be confusing. Those faces are from blocks. + private var visibleFluid = VisibleMeshes() // Fluids disable FACE_CULLING. Blocks that have waterlogged=true also twice private var cameraPosition = Vec3.EMPTY @@ -354,9 +357,9 @@ class WorldRenderer( val section = chunk[item.sectionHeight] ?: return@Runnable end() val neighbourChunks: Array = world.getChunkNeighbours(item.chunkPosition).unsafeCast() val neighbours = item.neighbours ?: ChunkUtil.getSectionNeighbours(neighbourChunks, chunk, item.sectionHeight) - item.solidMesh = sectionPreparer.prepareSolid(item.chunkPosition, item.sectionHeight, chunk, section, neighbours, neighbourChunks) + item.solidMesh = solidSectionPreparer.prepareSolid(item.chunkPosition, item.sectionHeight, chunk, section, neighbours, neighbourChunks) if (section.blocks.fluidCount > 0) { - item.fluidMesh = sectionPreparer.prepareFluid(item.chunkPosition, item.sectionHeight, chunk, section, neighbours, neighbourChunks) + item.fluidMesh = fluidSectionPreparer.prepareFluid(item.chunkPosition, item.sectionHeight, chunk, section, neighbours, neighbourChunks) } meshesToLoadLock.lock() locked = true diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/AbstractSectionPreparer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/FluidSectionPreparer.kt similarity index 66% rename from src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/AbstractSectionPreparer.kt rename to src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/FluidSectionPreparer.kt index 8e027f629..dacc81d4a 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/AbstractSectionPreparer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/FluidSectionPreparer.kt @@ -5,9 +5,7 @@ import de.bixilon.minosoft.data.world.ChunkSection import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh import glm_.vec2.Vec2i -interface AbstractSectionPreparer { - - fun prepareSolid(chunkPosition: Vec2i, sectionHeight: Int, chunk: Chunk, section: ChunkSection, neighbours: Array, neighbourChunks: Array): WorldMesh? +interface FluidSectionPreparer { fun prepareFluid(chunkPosition: Vec2i, sectionHeight: Int, chunk: Chunk, section: ChunkSection, neighbours: Array, neighbourChunks: Array): WorldMesh? } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/GreedySectionPreparer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/GreedySectionPreparer.kt index 084e88139..66e05a4f2 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/GreedySectionPreparer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/GreedySectionPreparer.kt @@ -31,7 +31,7 @@ import java.util.* @Deprecated("TODO") class GreedySectionPreparer( val renderWindow: RenderWindow, -) : AbstractSectionPreparer { +) : SolidSectionPreparer { private fun renderNormal(block: BlockState, directions: Directions?, position: Vec3i, section: ChunkSection, mesh: SingleWorldMesh, random: Random) { val neighbour = section.blocks[ChunkSection.getIndex(position.x, position.y, position.z)] @@ -235,8 +235,4 @@ class GreedySectionPreparer( TODO() } - - override fun prepareFluid(chunkPosition: Vec2i, sectionHeight: Int, chunk: Chunk, section: ChunkSection, neighbours: Array, neighbourChunks: Array): WorldMesh? { - TODO("Not yet implemented") - } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/SolidSectionPreparer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/SolidSectionPreparer.kt new file mode 100644 index 000000000..63f863616 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/SolidSectionPreparer.kt @@ -0,0 +1,11 @@ +package de.bixilon.minosoft.gui.rendering.world.preparer + +import de.bixilon.minosoft.data.world.Chunk +import de.bixilon.minosoft.data.world.ChunkSection +import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh +import glm_.vec2.Vec2i + +interface SolidSectionPreparer { + + fun prepareSolid(chunkPosition: Vec2i, sectionHeight: Int, chunk: Chunk, section: ChunkSection, neighbours: Array, neighbourChunks: Array): WorldMesh? +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/cull/FluidCullSectionPreparer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/cull/FluidCullSectionPreparer.kt new file mode 100644 index 000000000..1656b9693 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/cull/FluidCullSectionPreparer.kt @@ -0,0 +1,78 @@ +package de.bixilon.minosoft.gui.rendering.world.preparer.cull + +import de.bixilon.minosoft.data.registries.blocks.BlockState +import de.bixilon.minosoft.data.registries.blocks.properties.BlockProperties +import de.bixilon.minosoft.data.registries.blocks.types.FluidBlock +import de.bixilon.minosoft.data.registries.blocks.types.FluidFillable +import de.bixilon.minosoft.data.registries.fluid.DefaultFluids +import de.bixilon.minosoft.data.world.Chunk +import de.bixilon.minosoft.data.world.ChunkSection +import de.bixilon.minosoft.gui.rendering.RenderWindow +import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh +import de.bixilon.minosoft.gui.rendering.world.preparer.FluidSectionPreparer +import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition +import de.bixilon.minosoft.util.chunk.ChunkUtil.acquire +import de.bixilon.minosoft.util.chunk.ChunkUtil.release +import de.bixilon.minosoft.util.logging.Log +import de.bixilon.minosoft.util.logging.LogLevels +import de.bixilon.minosoft.util.logging.LogMessageType +import glm_.vec2.Vec2i +import glm_.vec3.Vec3i + +class FluidCullSectionPreparer( + val renderWindow: RenderWindow, +) : FluidSectionPreparer { + private val water = renderWindow.connection.registries.fluidRegistry[DefaultFluids.WATER] + private val tintColorCalculator = renderWindow.tintManager + + + override fun prepareFluid(chunkPosition: Vec2i, sectionHeight: Int, chunk: Chunk, section: ChunkSection, neighbours: Array, neighbourChunks: Array): WorldMesh? { + val mesh = WorldMesh(renderWindow, chunkPosition, sectionHeight, smallMesh = true) + + val isLowestSection = sectionHeight == chunk.lowestSection + val isHighestSection = sectionHeight == chunk.highestSection + val blocks = section.blocks + val sectionLight = section.light + section.acquire() + neighbours.acquire() + + var blockState: BlockState + var position: Vec3i + var rendered = false + var tints: IntArray? + + val offsetX = chunkPosition.x * ProtocolDefinition.SECTION_WIDTH_X + val offsetY = sectionHeight * ProtocolDefinition.SECTION_HEIGHT_Y + val offsetZ = chunkPosition.y * ProtocolDefinition.SECTION_WIDTH_Z + + 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) { + blockState = blocks.unsafeGet(x, y, z) ?: continue + val block = blockState.block + val fluid = when { + block is FluidBlock -> (blockState.block as FluidBlock).fluid + blockState.properties[BlockProperties.WATERLOGGED] == true && water != null -> water + block is FluidFillable -> block.fluid + else -> continue + } + Log.log(LogMessageType.OTHER, LogLevels.VERBOSE) { "Can not render fluid: $fluid" } + + + if (rendered) { + mesh.addBlock(x, y, z) + } + } + } + } + section.release() + neighbours.release() + + if (mesh.clearEmpty() == 0) { + return null + } + + return mesh + } + +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/CullSectionPreparer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/cull/SolidCullSectionPreparer.kt similarity index 74% rename from src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/CullSectionPreparer.kt rename to src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/cull/SolidCullSectionPreparer.kt index b3f6b7ec8..053b3c60b 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/CullSectionPreparer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/cull/SolidCullSectionPreparer.kt @@ -1,4 +1,4 @@ -package de.bixilon.minosoft.gui.rendering.world.preparer +package de.bixilon.minosoft.gui.rendering.world.preparer.cull import de.bixilon.minosoft.data.direction.Directions import de.bixilon.minosoft.data.direction.Directions.Companion.O_DOWN @@ -8,29 +8,24 @@ import de.bixilon.minosoft.data.direction.Directions.Companion.O_SOUTH import de.bixilon.minosoft.data.direction.Directions.Companion.O_UP import de.bixilon.minosoft.data.direction.Directions.Companion.O_WEST import de.bixilon.minosoft.data.registries.blocks.BlockState -import de.bixilon.minosoft.data.registries.blocks.properties.BlockProperties import de.bixilon.minosoft.data.registries.blocks.types.FluidBlock -import de.bixilon.minosoft.data.registries.fluid.DefaultFluids import de.bixilon.minosoft.data.world.Chunk import de.bixilon.minosoft.data.world.ChunkSection import de.bixilon.minosoft.gui.rendering.RenderWindow import de.bixilon.minosoft.gui.rendering.models.baked.block.BakedBlockModel import de.bixilon.minosoft.gui.rendering.util.VecUtil import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh +import de.bixilon.minosoft.gui.rendering.world.preparer.SolidSectionPreparer import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition import de.bixilon.minosoft.util.chunk.ChunkUtil.acquire import de.bixilon.minosoft.util.chunk.ChunkUtil.release -import de.bixilon.minosoft.util.logging.Log -import de.bixilon.minosoft.util.logging.LogLevels -import de.bixilon.minosoft.util.logging.LogMessageType import glm_.vec2.Vec2i import glm_.vec3.Vec3i import java.util.* -class CullSectionPreparer( +class SolidCullSectionPreparer( val renderWindow: RenderWindow, -) : AbstractSectionPreparer { - private val water = renderWindow.connection.registries.fluidRegistry[DefaultFluids.WATER] +) : SolidSectionPreparer { private val tintColorCalculator = renderWindow.tintManager private val ambientLight = floatArrayOf(1.0f, 1.0f, 1.0f, 1.0f) @@ -141,50 +136,4 @@ class CullSectionPreparer( return mesh } - - override fun prepareFluid(chunkPosition: Vec2i, sectionHeight: Int, chunk: Chunk, section: ChunkSection, neighbours: Array, neighbourChunks: Array): WorldMesh? { - val mesh = WorldMesh(renderWindow, chunkPosition, sectionHeight, smallMesh = true) - - val isLowestSection = sectionHeight == chunk.lowestSection - val isHighestSection = sectionHeight == chunk.highestSection - val blocks = section.blocks - val sectionLight = section.light - section.acquire() - neighbours.acquire() - - var blockState: BlockState - var position: Vec3i - var rendered = false - var tints: IntArray? - - val offsetX = chunkPosition.x * ProtocolDefinition.SECTION_WIDTH_X - val offsetY = sectionHeight * ProtocolDefinition.SECTION_HEIGHT_Y - val offsetZ = chunkPosition.y * ProtocolDefinition.SECTION_WIDTH_Z - - 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) { - blockState = blocks.unsafeGet(x, y, z) ?: continue - val fluid = when { - blockState.block is FluidBlock -> (blockState.block as FluidBlock).fluid - blockState.properties[BlockProperties.WATERLOGGED] == true && water != null -> water - else -> continue - } - Log.log(LogMessageType.OTHER, LogLevels.VERBOSE) { "Can not render fluid: $fluid" } - - if (rendered) { - mesh.addBlock(x, y, z) - } - } - } - } - section.release() - neighbours.release() - - if (mesh.clearEmpty() == 0) { - return null - } - - return mesh - } }