diff --git a/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/chunk/mesher/SolidSectionMesherTest.kt b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/chunk/mesher/SolidSectionMesherTest.kt new file mode 100644 index 000000000..61d63d9b5 --- /dev/null +++ b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/chunk/mesher/SolidSectionMesherTest.kt @@ -0,0 +1,466 @@ +/* + * Minosoft + * Copyright (C) 2020-2023 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 . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.chunk.mesher + +import de.bixilon.kotlinglm.vec2.Vec2 +import de.bixilon.kotlinglm.vec3.Vec3i +import de.bixilon.kutil.exception.Broken +import de.bixilon.kutil.reflection.ReflectionUtil.forceSet +import de.bixilon.minosoft.data.container.stack.ItemStack +import de.bixilon.minosoft.data.direction.Directions +import de.bixilon.minosoft.data.entities.block.BlockEntity +import de.bixilon.minosoft.data.entities.block.MeshedBlockEntity +import de.bixilon.minosoft.data.registries.blocks.settings.BlockSettings +import de.bixilon.minosoft.data.registries.blocks.state.BlockState +import de.bixilon.minosoft.data.registries.blocks.types.Block +import de.bixilon.minosoft.data.registries.blocks.types.entity.BlockWithEntity +import de.bixilon.minosoft.data.registries.dimension.DimensionProperties +import de.bixilon.minosoft.data.registries.identified.Namespaces.minosoft +import de.bixilon.minosoft.data.world.positions.BlockPosition +import de.bixilon.minosoft.gui.rendering.RenderContext +import de.bixilon.minosoft.gui.rendering.camera.Camera +import de.bixilon.minosoft.gui.rendering.chunk.entities.BlockEntityRenderer +import de.bixilon.minosoft.gui.rendering.chunk.entities.MeshedEntityRenderer +import de.bixilon.minosoft.gui.rendering.chunk.mesh.ChunkMeshes +import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer +import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer +import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions +import de.bixilon.minosoft.gui.rendering.models.block.state.baked.cull.side.FaceProperties +import de.bixilon.minosoft.gui.rendering.models.block.state.baked.cull.side.SideProperties +import de.bixilon.minosoft.gui.rendering.models.block.state.render.BlockRender +import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureTransparencies +import de.bixilon.minosoft.gui.rendering.system.dummy.DummyRenderSystem +import de.bixilon.minosoft.gui.rendering.tint.TintManager +import de.bixilon.minosoft.gui.rendering.tint.TintedBlock +import de.bixilon.minosoft.gui.rendering.tint.tints.StaticTintProvider +import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2Util.EMPTY +import de.bixilon.minosoft.protocol.network.connection.play.ConnectionTestUtil +import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection +import de.bixilon.minosoft.test.IT +import org.testng.Assert.assertEquals +import org.testng.annotations.Test +import java.util.* + +@Test(groups = ["mesher"], dependsOnGroups = ["rendering", "block"]) +class SolidSectionMesherTest { + + private fun createContext(connection: PlayConnection): RenderContext { + val context = IT.OBJENESIS.newInstance(RenderContext::class.java) + context::connection.forceSet(connection) + context::system.forceSet(DummyRenderSystem(context)) + context::camera.forceSet(Camera(context)) + context::tints.forceSet(TintManager(connection)) + + + return context + } + + private fun createConnection(blocks: Map): PlayConnection { + val connection = ConnectionTestUtil.createConnection(worldSize = 2) + for ((position, block) in blocks) { + connection.world[position] = block!! + } + + return connection + } + + private fun PlayConnection.mesh(): ChunkMeshes { + val context = createContext(this) + val mesher = SolidSectionMesher(context) + + val chunk = world.chunks[0, 0]!! + val meshes = ChunkMeshes(context, chunk.chunkPosition, 0, true) + + mesher.mesh(chunk.chunkPosition, 0, chunk, chunk.sections[0]!!, chunk.neighbours.get()!!, chunk.sections[0]!!.neighbours!!, meshes) + + return meshes + } + + + private fun mesh(blocks: Map): ChunkMeshes { + val connection = createConnection(blocks) + + return connection.mesh() + } + + fun `test simple stone block`() { + val queue = TestQueue() + val stone = queue.fullOpaque() + val meshes = mesh(mapOf(Vec3i(2, 2, 2) to stone)) + + queue.assert( + TestQueue.RenderedBlock(Vec3i(2, 2, 2), stone), + ) + + assertEquals(meshes.minPosition, Vec3i(2, 2, 2)) + assertEquals(meshes.maxPosition, Vec3i(2, 2, 2)) + } + + fun `tinted and untinted block`() { + val queue = TestQueue() + val untinted = queue.fullOpaque() + val tinted = queue.tinted() + mesh(mapOf( + Vec3i(2, 2, 2) to untinted, + Vec3i(2, 3, 2) to tinted, + )) + + queue.assert( + TestQueue.RenderedBlock(Vec3i(2, 2, 2), untinted), + TestQueue.RenderedBlock(Vec3i(2, 3, 2), tinted, 0x123456), + ) + } + + fun `test 2 stone block in extreme directions`() { + val queue = TestQueue() + val stone = queue.fullOpaque() + val meshes = mesh(mapOf( + Vec3i(0, 0, 0) to stone, + Vec3i(15, 15, 15) to stone, + )) + + queue.assert( + TestQueue.RenderedBlock(Vec3i(0, 0, 0), stone), + TestQueue.RenderedBlock(Vec3i(15, 15, 15), stone), + ) + + assertEquals(meshes.minPosition, Vec3i(0, 0, 0)) + assertEquals(meshes.maxPosition, Vec3i(15, 15, 15)) + assertEquals(meshes.blockEntities?.size, 0) + } + + fun `optimize out when all neighbour blocks are full opaque`() { + val queue = TestQueue() + val stone = queue.fullOpaque() + val small = queue.nonTouching() + mesh(mapOf( + Vec3i(2, 1, 2) to stone, + Vec3i(2, 3, 2) to stone, + Vec3i(2, 2, 1) to stone, + Vec3i(2, 2, 3) to stone, + Vec3i(1, 2, 2) to stone, + Vec3i(3, 2, 2) to stone, + + Vec3i(2, 2, 2) to small, + )) + + queue.assert( + TestQueue.RenderedBlock(Vec3i(2, 1, 2), stone), + TestQueue.RenderedBlock(Vec3i(2, 3, 2), stone), + TestQueue.RenderedBlock(Vec3i(2, 2, 1), stone), + TestQueue.RenderedBlock(Vec3i(2, 2, 3), stone), + TestQueue.RenderedBlock(Vec3i(1, 2, 2), stone), + TestQueue.RenderedBlock(Vec3i(3, 2, 2), stone), + ) + } + + fun `render stub block entity`() { + val queue = TestQueue() + val entity = queue.blockEntity() + val stone = queue.fullOpaque() + val meshes = mesh(mapOf( + Vec3i(2, 2, 2) to entity, + Vec3i(2, 5, 2) to stone, + )) + + queue.assert( + TestQueue.RenderedBlock(Vec3i(2, 5, 2), stone), + ) + queue.assert( + TestQueue.RenderedEntity(Vec3i(2, 2, 2), entity), + ) + assertEquals(meshes.blockEntities?.size, 1) + } + + fun `optimize out block entity if all neighbour blocks are full opaque`() { + val queue = TestQueue() + val entity = queue.blockEntity() + val stone = queue.fullOpaque() + mesh(mapOf( + Vec3i(2, 1, 2) to stone, + Vec3i(2, 3, 2) to stone, + Vec3i(2, 2, 1) to stone, + Vec3i(2, 2, 3) to stone, + Vec3i(1, 2, 2) to stone, + Vec3i(3, 2, 2) to stone, + + Vec3i(2, 2, 2) to entity, + )) + + queue.assert( + TestQueue.RenderedBlock(Vec3i(2, 1, 2), stone), + TestQueue.RenderedBlock(Vec3i(2, 3, 2), stone), + TestQueue.RenderedBlock(Vec3i(2, 2, 1), stone), + TestQueue.RenderedBlock(Vec3i(2, 2, 3), stone), + TestQueue.RenderedBlock(Vec3i(1, 2, 2), stone), + TestQueue.RenderedBlock(Vec3i(3, 2, 2), stone), + ) + assertEquals(queue.entities.size, 0) + } + + fun `not optimize out block entity if one neighbour blocks is not full opaque`() { + val queue = TestQueue() + val stone = queue.fullOpaque() + val small = queue.nonTouching() + mesh(mapOf( + Vec3i(2, 1, 2) to stone, + Vec3i(2, 3, 2) to stone, + Vec3i(1, 2, 2) to stone, + Vec3i(3, 2, 2) to stone, + Vec3i(2, 2, 1) to stone, + Vec3i(2, 2, 3) to small, + + Vec3i(2, 2, 2) to stone, + )) + + queue.assert( + TestQueue.RenderedBlock(Vec3i(2, 1, 2), stone), + TestQueue.RenderedBlock(Vec3i(2, 3, 2), stone), + TestQueue.RenderedBlock(Vec3i(2, 2, 1), stone), + TestQueue.RenderedBlock(Vec3i(2, 2, 3), small), + TestQueue.RenderedBlock(Vec3i(1, 2, 2), stone), + TestQueue.RenderedBlock(Vec3i(3, 2, 2), stone), + + TestQueue.RenderedBlock(Vec3i(2, 2, 2), stone), + ) + assertEquals(queue.entities.size, 0) + } + + fun `render meshed`() { + val queue = TestQueue() + val entity = queue.blockEntity() + val stone = queue.fullOpaque() + mesh(mapOf( + Vec3i(2, 2, 2) to entity, + Vec3i(2, 5, 2) to stone, + )) + + queue.assert( + TestQueue.RenderedBlock(Vec3i(2, 5, 2), stone), + ) + queue.assert( + TestQueue.RenderedEntity(Vec3i(2, 2, 2), entity), + ) + } + + fun `render meshed only`() { + val queue = TestQueue() + val entity = queue.meshedOnlyEntity() + val stone = queue.fullOpaque() + mesh(mapOf( + Vec3i(2, 2, 2) to entity, + Vec3i(2, 5, 2) to stone, + )) + + queue.assert( + TestQueue.RenderedBlock(Vec3i(2, 5, 2), stone), + ) + queue.assert( + TestQueue.RenderedEntity(Vec3i(2, 2, 2), entity, true), + ) + } + + private operator fun ByteArray.set(x: Int, y: Int, z: Int, value: Int) { + val index = (y shl 8) or (z shl 4) or x + this[index] = value.toByte() + } + + fun `simple light`() { + val queue = TestQueue() + val stone = queue.lighted() + val connection = createConnection(emptyMap()) + connection.world.dimension = DimensionProperties() + connection.world[Vec3i(6, 7, 9)] = stone + val chunk = connection.world.chunks[0, 0]!! + val section = chunk.sections[0]!! + section.light.light[6, 6, 9] = 0x01 + section.light.light[6, 8, 9] = 0x02 + section.light.light[6, 7, 8] = 0x03 + section.light.light[6, 7, 10] = 0x04 + section.light.light[5, 7, 9] = 0x05 + section.light.light[7, 7, 9] = 0x06 + + section.light.light[6, 7, 9] = 0x07 + + connection.mesh() + } + + fun `neighbours are correctly set`() { + val queue = TestQueue() + val blocks = Array(6) { queue.nonTouching(it) } + mesh(mapOf( + Vec3i(2, 1, 2) to blocks[0], + Vec3i(2, 3, 2) to blocks[1], + Vec3i(2, 2, 1) to blocks[2], + Vec3i(2, 2, 3) to blocks[3], + Vec3i(1, 2, 2) to blocks[4], + Vec3i(3, 2, 2) to blocks[5], + + Vec3i(2, 2, 2) to queue.neighbours(blocks), + )) + + assertEquals(queue.blocks.size, 7) + } + // TODO: test sign block entity rendering + // TODO: test skylight (w/ heightmap), correct neighbour retrieving, fast bedrock, camera offset + + class TestQueue { + val blocks: MutableSet = mutableSetOf() + val entities: MutableSet = mutableSetOf() + + + fun assert(vararg blocks: RenderedBlock) { + assertEquals(this.blocks, blocks.toSet()) + } + + fun assert(vararg entities: RenderedEntity) { + assertEquals(this.entities, entities.toSet()) + } + + data class RenderedBlock( + val position: Vec3i, + val block: BlockState, + val tint: Int? = null, + ) + + data class RenderedEntity( + val position: Vec3i, + val block: BlockState, + val meshed: Boolean = false, + ) + } + + fun block(index: Int = 0): Block = object : Block(minosoft("test$index"), BlockSettings.of(IT.VERSION, IT.REGISTRIES, emptyMap())) { + override val hardness get() = 0.0f + } + + fun TestQueue.fullOpaque(index: Int = 0): BlockState { + val state = BlockState(block(index), 0) + state.model = TestModel(this, SideProperties(arrayOf(FaceProperties(Vec2.EMPTY, Vec2(1.0f), TextureTransparencies.OPAQUE)), TextureTransparencies.OPAQUE)) + + return state + } + + fun TestQueue.nonTouching(index: Int = 0): BlockState { + val state = BlockState(block(index), 0) + state.model = TestModel(this, null) + + return state + } + + fun TestQueue.tinted(): BlockState { + val block = object : Block(minosoft("test3"), BlockSettings.of(IT.VERSION, IT.REGISTRIES, emptyMap())), TintedBlock { + override val hardness get() = 0.0f + override val tintProvider = StaticTintProvider(0x123456) + } + val state = BlockState(block, 0) + state.model = TestModel(this, null) + + return state + } + + fun TestQueue.lighted(required: IntArray = IntArray(7) { it + 1 }): BlockState { + val block = object : Block(minosoft("testdroelf"), BlockSettings.of(IT.VERSION, IT.REGISTRIES, emptyMap())) { + override val hardness get() = 0.0f + } + val state = BlockState(block, 0) + state.model = object : TestModel(this, null) { + override fun render(position: BlockPosition, offset: FloatArray, mesh: ChunkMeshes, random: Random?, state: BlockState, neighbours: Array, light: ByteArray, tints: IntArray?): Boolean { + assertEquals(light.size, 7) + for ((index, entry) in light.withIndex()) { + assertEquals(required[index], entry.toInt() and 0xFF) + } + return super.render(position, offset, mesh, random, state, neighbours, light, tints) + } + } + + return state + } + + fun TestQueue.neighbours(required: Array): BlockState { + val block = object : Block(minosoft("testdroelfe"), BlockSettings.of(IT.VERSION, IT.REGISTRIES, emptyMap())) { + override val hardness get() = 0.0f + } + val state = BlockState(block, 0) + state.model = object : TestModel(this, null) { + override fun render(position: BlockPosition, offset: FloatArray, mesh: ChunkMeshes, random: Random?, state: BlockState, neighbours: Array, light: ByteArray, tints: IntArray?): Boolean { + assertEquals(neighbours.size, 6) + for ((index, entry) in neighbours.withIndex()) { + assertEquals(required[index], entry) + } + return super.render(position, offset, mesh, random, state, neighbours, light, tints) + } + } + + return state + } + + fun TestQueue.blockEntity(): BlockState { + val block = object : Block(minosoft("test2"), BlockSettings.of(IT.VERSION, IT.REGISTRIES, emptyMap())), BlockWithEntity { + override val hardness get() = 0.0f + override fun createBlockEntity(connection: PlayConnection) = object : BlockEntity(connection) { + + override fun createRenderer(context: RenderContext, state: BlockState, position: Vec3i, light: Int) = object : BlockEntityRenderer { + override var light = 0 + override var state = state + + init { + + entities.add(TestQueue.RenderedEntity(Vec3i(position), state, false)).let { if (!it) throw IllegalArgumentException("Twice!!!") } + } + } + } + } + val state = BlockState(block, 0) + + return state + } + + fun TestQueue.meshedOnlyEntity(): BlockState { + val block = object : Block(minosoft("test4"), BlockSettings.of(IT.VERSION, IT.REGISTRIES, emptyMap())), BlockWithEntity { + override val hardness get() = 0.0f + override fun createBlockEntity(connection: PlayConnection) = object : MeshedBlockEntity(connection) { + + override fun createMeshedRenderer(context: RenderContext, state: BlockState, position: Vec3i) = object : MeshedEntityRenderer { + override var state: BlockState = state + override var light: Int = 0xFF + + override fun render(position: BlockPosition, offset: FloatArray, mesh: ChunkMeshes, random: Random?, state: BlockState, neighbours: Array, light: ByteArray, tints: IntArray?): Boolean { + entities.add(TestQueue.RenderedEntity(Vec3i(position), state, true)).let { if (!it) throw IllegalArgumentException("Twice!!!") } + + return true + } + + override fun render(gui: GUIRenderer, offset: Vec2, consumer: GUIVertexConsumer, options: GUIVertexOptions?, size: Vec2, stack: ItemStack) = Broken() + } + } + } + val state = BlockState(block, 0) + + return state + } + + private open class TestModel(val queue: TestQueue, val properties: SideProperties?) : BlockRender { + + override fun render(gui: GUIRenderer, offset: Vec2, consumer: GUIVertexConsumer, options: GUIVertexOptions?, size: Vec2, stack: ItemStack) = Broken() + override fun getProperties(direction: Directions): SideProperties? { + return this.properties + } + + override fun render(position: BlockPosition, offset: FloatArray, mesh: ChunkMeshes, random: Random?, state: BlockState, neighbours: Array, light: ByteArray, tints: IntArray?): Boolean { + queue.blocks.add(TestQueue.RenderedBlock(Vec3i(position), state, tints?.getOrNull(0))).let { if (!it) throw IllegalArgumentException("Twice!!!") } + return true + } + } +} diff --git a/src/main/java/de/bixilon/minosoft/data/entities/block/MeshedBlockEntity.kt b/src/main/java/de/bixilon/minosoft/data/entities/block/MeshedBlockEntity.kt index 24a527090..25df867f8 100644 --- a/src/main/java/de/bixilon/minosoft/data/entities/block/MeshedBlockEntity.kt +++ b/src/main/java/de/bixilon/minosoft/data/entities/block/MeshedBlockEntity.kt @@ -36,5 +36,5 @@ abstract class MeshedBlockEntity(connection: PlayConnection) : BlockEntity(conne throw IllegalAccessException() } - abstract fun createMeshedRenderer(context: RenderContext, blockState: BlockState, blockPosition: Vec3i): MeshedEntityRenderer<*> + abstract fun createMeshedRenderer(context: RenderContext, state: BlockState, position: Vec3i): MeshedEntityRenderer<*> } diff --git a/src/main/java/de/bixilon/minosoft/data/entities/block/sign/SignBlockEntity.kt b/src/main/java/de/bixilon/minosoft/data/entities/block/sign/SignBlockEntity.kt index 20f6719af..7c0d8f00f 100644 --- a/src/main/java/de/bixilon/minosoft/data/entities/block/sign/SignBlockEntity.kt +++ b/src/main/java/de/bixilon/minosoft/data/entities/block/sign/SignBlockEntity.kt @@ -44,8 +44,8 @@ class SignBlockEntity(connection: PlayConnection) : MeshedBlockEntity(connection // TODO: update front/back text } - override fun createMeshedRenderer(context: RenderContext, blockState: BlockState, blockPosition: Vec3i): SignBlockEntityRenderer { - return SignBlockEntityRenderer(this, context, blockState) + override fun createMeshedRenderer(context: RenderContext, state: BlockState, position: Vec3i): SignBlockEntityRenderer { + return SignBlockEntityRenderer(this, context, state) } companion object : BlockEntityFactory { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/mesh/ChunkMesh.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/mesh/ChunkMesh.kt index 597d4b65f..6a7a147ca 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/mesh/ChunkMesh.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/mesh/ChunkMesh.kt @@ -16,6 +16,7 @@ package de.bixilon.minosoft.gui.rendering.chunk.mesh import de.bixilon.kotlinglm.vec2.Vec2 import de.bixilon.kotlinglm.vec3.Vec3 import de.bixilon.minosoft.gui.rendering.RenderContext +import de.bixilon.minosoft.gui.rendering.models.block.element.FaceVertexData import de.bixilon.minosoft.gui.rendering.system.base.MeshUtil.buffer import de.bixilon.minosoft.gui.rendering.system.base.texture.shader.ShaderTexture import de.bixilon.minosoft.gui.rendering.util.mesh.Mesh @@ -37,11 +38,11 @@ class ChunkMesh(context: RenderContext, initialCacheSize: Int, onDemand: Boolean ) } - inline fun addVertex(x: Float, y: Float, z: Float, u: Float, v: Float, shaderTextureId: Float, lightTint: Float) { + inline fun addVertex(x: Float, y: Float, z: Float, u: Float, v: Float, textureId: Float, lightTint: Float) { data.add( x, y, z, u, v, - shaderTextureId, lightTint, + textureId, lightTint, ) } @@ -51,6 +52,22 @@ class ChunkMesh(context: RenderContext, initialCacheSize: Int, onDemand: Boolean return 0 } + fun addQuad(offset: FloatArray, positions: FaceVertexData, uvData: FaceVertexData, textureId: Float, lightTint: Float) { + data.ensureSize(ChunkMeshStruct.FLOATS_PER_VERTEX * order.size) + + order.iterate { position, uv -> + val vertexOffset = position * Vec3.length + val uvOffset = uv * Vec2.length + addVertex( + x = offset[0] + positions[vertexOffset], y = offset[1] + positions[vertexOffset + 1], z = offset[2] + positions[vertexOffset + 2], + u = uvData[uvOffset], + v = uvData[uvOffset + 1], + textureId = textureId, + lightTint = lightTint, + ) + } + } + data class ChunkMeshStruct( val position: Vec3, val uv: Vec2, diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/model/human/HumanModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/model/human/HumanModel.kt index be108e7be..8765f4031 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/model/human/HumanModel.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/model/human/HumanModel.kt @@ -13,8 +13,6 @@ package de.bixilon.minosoft.gui.rendering.entities.model.human -import de.bixilon.minosoft.data.entities.Poses -import de.bixilon.minosoft.data.entities.entities.LivingEntity import de.bixilon.minosoft.gui.rendering.entities.feature.SkeletalFeature import de.bixilon.minosoft.gui.rendering.entities.model.human.animator.ArmAnimator import de.bixilon.minosoft.gui.rendering.entities.model.human.animator.HeadPosition @@ -29,18 +27,12 @@ abstract class HumanModel>(renderer: R, model: BakedSkelet val arm = ArmAnimator(this, instance.transform.children["left_arm"]!!, instance.transform.children["right_arm"]!!) val speed = EntitySpeed(renderer.entity) - var pose = Poses.STANDING + override fun updatePosition() { super.updatePosition() head?.update() } - fun updatePose() { - val entity =renderer.entity - if(entity !is LivingEntity) return - val pose = entity.pose ?: return - } - override fun update(millis: Long, delta: Float) { speed.update(delta) super.update(millis, delta) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/baked/BakedFace.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/baked/BakedFace.kt index 1658aca57..ec87ada38 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/baked/BakedFace.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/baked/BakedFace.kt @@ -13,8 +13,6 @@ package de.bixilon.minosoft.gui.rendering.models.block.state.baked -import de.bixilon.kotlinglm.vec2.Vec2 -import de.bixilon.kotlinglm.vec3.Vec3 import de.bixilon.minosoft.data.direction.Directions import de.bixilon.minosoft.gui.rendering.chunk.mesh.ChunkMesh import de.bixilon.minosoft.gui.rendering.chunk.mesh.ChunkMeshes @@ -53,19 +51,7 @@ class BakedFace( val mesh = mesh.mesh(texture) - mesh.data.ensureSize(ChunkMesh.ChunkMeshStruct.FLOATS_PER_VERTEX * mesh.order.size) - - mesh.order.iterate { position, uv -> - val vertexOffset = position * Vec3.length - val uvOffset = uv * Vec2.length - mesh.addVertex( - x = offset[0] + positions[vertexOffset], y = offset[1] + positions[vertexOffset + 1], z = offset[2] + positions[vertexOffset + 2], - u = this.uv[uvOffset], - v = this.uv[uvOffset + 1], - shaderTextureId = textureId, - lightTint = lightTint, - ) - } + mesh.addQuad(offset, this.positions, this.uv, textureId, lightTint) } private fun ChunkMeshes.mesh(texture: Texture): ChunkMesh {