mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-17 19:35:00 -04:00
count FluidFillable blocks as fluid, restructure some fluid stuff
This commit is contained in:
parent
1fdb1b6403
commit
5fc6b606bb
@ -13,8 +13,8 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.data.registries.blocks.types
|
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 {
|
interface FluidFillable {
|
||||||
val fluid: ResourceLocation
|
val fluid: Fluid
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package de.bixilon.minosoft.data.world.container
|
package de.bixilon.minosoft.data.world.container
|
||||||
|
|
||||||
import de.bixilon.minosoft.data.registries.blocks.BlockState
|
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.FluidBlock
|
||||||
|
import de.bixilon.minosoft.data.registries.blocks.types.FluidFillable
|
||||||
import de.bixilon.minosoft.util.KUtil.unsafeCast
|
import de.bixilon.minosoft.util.KUtil.unsafeCast
|
||||||
|
|
||||||
class BlockSectionDataProvider(
|
class BlockSectionDataProvider(
|
||||||
@ -16,7 +18,7 @@ class BlockSectionDataProvider(
|
|||||||
|
|
||||||
fluidCount = 0
|
fluidCount = 0
|
||||||
for (blockState in data) {
|
for (blockState in data) {
|
||||||
if (blockState?.block is FluidBlock) {
|
if (blockState.isFluid()) {
|
||||||
fluidCount++
|
fluidCount++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -24,13 +26,29 @@ class BlockSectionDataProvider(
|
|||||||
|
|
||||||
override fun set(index: Int, value: BlockState?): BlockState? {
|
override fun set(index: Int, value: BlockState?): BlockState? {
|
||||||
val previous = super.set(index, value)
|
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++
|
fluidCount++
|
||||||
} else if (previous?.block is FluidBlock && value?.block !is FluidBlock) {
|
} else if (previousFluid && !valueFluid) {
|
||||||
fluidCount--
|
fluidCount--
|
||||||
}
|
}
|
||||||
|
|
||||||
return previous
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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.SectionMesh
|
||||||
import de.bixilon.minosoft.gui.rendering.world.mesh.VisibleMeshes
|
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.mesh.WorldMesh
|
||||||
import de.bixilon.minosoft.gui.rendering.world.preparer.AbstractSectionPreparer
|
import de.bixilon.minosoft.gui.rendering.world.preparer.FluidSectionPreparer
|
||||||
import de.bixilon.minosoft.gui.rendering.world.preparer.CullSectionPreparer
|
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.*
|
||||||
import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionStateChangeEvent
|
import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionStateChangeEvent
|
||||||
import de.bixilon.minosoft.modding.event.invoker.CallbackEventInvoker
|
import de.bixilon.minosoft.modding.event.invoker.CallbackEventInvoker
|
||||||
@ -84,7 +86,8 @@ class WorldRenderer(
|
|||||||
private val shader = renderSystem.createShader("minosoft:world".toResourceLocation())
|
private val shader = renderSystem.createShader("minosoft:world".toResourceLocation())
|
||||||
private val transparentShader = renderSystem.createShader("minosoft:world".toResourceLocation())
|
private val transparentShader = renderSystem.createShader("minosoft:world".toResourceLocation())
|
||||||
private val world: World = connection.world
|
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 lightMap = LightMap(connection)
|
||||||
|
|
||||||
private val loadedMeshes: MutableMap<Vec2i, MutableMap<Int, SectionMesh>> = mutableMapOf() // all prepared (and up to date) meshes
|
private val loadedMeshes: MutableMap<Vec2i, MutableMap<Int, SectionMesh>> = 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, ...)
|
// 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 clearVisibleNextFrame = false
|
||||||
private var visibleSolid = VisibleMeshes()
|
private var visibleSolid = VisibleMeshes() // This name might be confusing. Those faces are from blocks.
|
||||||
private var visibleFluid = VisibleMeshes()
|
private var visibleFluid = VisibleMeshes() // Fluids disable FACE_CULLING. Blocks that have waterlogged=true also twice
|
||||||
|
|
||||||
|
|
||||||
private var cameraPosition = Vec3.EMPTY
|
private var cameraPosition = Vec3.EMPTY
|
||||||
@ -354,9 +357,9 @@ class WorldRenderer(
|
|||||||
val section = chunk[item.sectionHeight] ?: return@Runnable end()
|
val section = chunk[item.sectionHeight] ?: return@Runnable end()
|
||||||
val neighbourChunks: Array<Chunk> = world.getChunkNeighbours(item.chunkPosition).unsafeCast()
|
val neighbourChunks: Array<Chunk> = world.getChunkNeighbours(item.chunkPosition).unsafeCast()
|
||||||
val neighbours = item.neighbours ?: ChunkUtil.getSectionNeighbours(neighbourChunks, chunk, item.sectionHeight)
|
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) {
|
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()
|
meshesToLoadLock.lock()
|
||||||
locked = true
|
locked = true
|
||||||
|
@ -5,9 +5,7 @@ import de.bixilon.minosoft.data.world.ChunkSection
|
|||||||
import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh
|
import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh
|
||||||
import glm_.vec2.Vec2i
|
import glm_.vec2.Vec2i
|
||||||
|
|
||||||
interface AbstractSectionPreparer {
|
interface FluidSectionPreparer {
|
||||||
|
|
||||||
fun prepareSolid(chunkPosition: Vec2i, sectionHeight: Int, chunk: Chunk, section: ChunkSection, neighbours: Array<ChunkSection?>, neighbourChunks: Array<Chunk>): WorldMesh?
|
|
||||||
|
|
||||||
fun prepareFluid(chunkPosition: Vec2i, sectionHeight: Int, chunk: Chunk, section: ChunkSection, neighbours: Array<ChunkSection?>, neighbourChunks: Array<Chunk>): WorldMesh?
|
fun prepareFluid(chunkPosition: Vec2i, sectionHeight: Int, chunk: Chunk, section: ChunkSection, neighbours: Array<ChunkSection?>, neighbourChunks: Array<Chunk>): WorldMesh?
|
||||||
}
|
}
|
@ -31,7 +31,7 @@ import java.util.*
|
|||||||
@Deprecated("TODO")
|
@Deprecated("TODO")
|
||||||
class GreedySectionPreparer(
|
class GreedySectionPreparer(
|
||||||
val renderWindow: RenderWindow,
|
val renderWindow: RenderWindow,
|
||||||
) : AbstractSectionPreparer {
|
) : SolidSectionPreparer {
|
||||||
|
|
||||||
private fun renderNormal(block: BlockState, directions: Directions?, position: Vec3i, section: ChunkSection, mesh: SingleWorldMesh, random: Random) {
|
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)]
|
val neighbour = section.blocks[ChunkSection.getIndex(position.x, position.y, position.z)]
|
||||||
@ -235,8 +235,4 @@ class GreedySectionPreparer(
|
|||||||
|
|
||||||
TODO()
|
TODO()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun prepareFluid(chunkPosition: Vec2i, sectionHeight: Int, chunk: Chunk, section: ChunkSection, neighbours: Array<ChunkSection?>, neighbourChunks: Array<Chunk>): WorldMesh? {
|
|
||||||
TODO("Not yet implemented")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -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<ChunkSection?>, neighbourChunks: Array<Chunk>): WorldMesh?
|
||||||
|
}
|
@ -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<ChunkSection?>, neighbourChunks: Array<Chunk>): 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
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -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
|
||||||
import de.bixilon.minosoft.data.direction.Directions.Companion.O_DOWN
|
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_UP
|
||||||
import de.bixilon.minosoft.data.direction.Directions.Companion.O_WEST
|
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.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.FluidBlock
|
||||||
import de.bixilon.minosoft.data.registries.fluid.DefaultFluids
|
|
||||||
import de.bixilon.minosoft.data.world.Chunk
|
import de.bixilon.minosoft.data.world.Chunk
|
||||||
import de.bixilon.minosoft.data.world.ChunkSection
|
import de.bixilon.minosoft.data.world.ChunkSection
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
import de.bixilon.minosoft.gui.rendering.RenderWindow
|
||||||
import de.bixilon.minosoft.gui.rendering.models.baked.block.BakedBlockModel
|
import de.bixilon.minosoft.gui.rendering.models.baked.block.BakedBlockModel
|
||||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil
|
import de.bixilon.minosoft.gui.rendering.util.VecUtil
|
||||||
import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh
|
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.protocol.protocol.ProtocolDefinition
|
||||||
import de.bixilon.minosoft.util.chunk.ChunkUtil.acquire
|
import de.bixilon.minosoft.util.chunk.ChunkUtil.acquire
|
||||||
import de.bixilon.minosoft.util.chunk.ChunkUtil.release
|
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_.vec2.Vec2i
|
||||||
import glm_.vec3.Vec3i
|
import glm_.vec3.Vec3i
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class CullSectionPreparer(
|
class SolidCullSectionPreparer(
|
||||||
val renderWindow: RenderWindow,
|
val renderWindow: RenderWindow,
|
||||||
) : AbstractSectionPreparer {
|
) : SolidSectionPreparer {
|
||||||
private val water = renderWindow.connection.registries.fluidRegistry[DefaultFluids.WATER]
|
|
||||||
private val tintColorCalculator = renderWindow.tintManager
|
private val tintColorCalculator = renderWindow.tintManager
|
||||||
private val ambientLight = floatArrayOf(1.0f, 1.0f, 1.0f, 1.0f)
|
private val ambientLight = floatArrayOf(1.0f, 1.0f, 1.0f, 1.0f)
|
||||||
|
|
||||||
@ -141,50 +136,4 @@ class CullSectionPreparer(
|
|||||||
|
|
||||||
return mesh
|
return mesh
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun prepareFluid(chunkPosition: Vec2i, sectionHeight: Int, chunk: Chunk, section: ChunkSection, neighbours: Array<ChunkSection?>, neighbourChunks: Array<Chunk>): 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
|
|
||||||
}
|
|
||||||
}
|
}
|
Loading…
x
Reference in New Issue
Block a user