diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/feature/item/ItemFeature.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/feature/item/ItemFeature.kt index 0f1ff93c7..9c86f6140 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/feature/item/ItemFeature.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/feature/item/ItemFeature.kt @@ -17,6 +17,8 @@ import de.bixilon.kotlinglm.mat4x4.Mat4 import de.bixilon.kutil.random.RandomUtil.nextFloat import de.bixilon.minosoft.data.container.stack.ItemStack import de.bixilon.minosoft.gui.rendering.entities.feature.block.BlockMesh +import de.bixilon.minosoft.gui.rendering.entities.feature.block.BlockShader +import de.bixilon.minosoft.gui.rendering.entities.feature.item.ItemFeature.ItemRenderDistance.Companion.getCount import de.bixilon.minosoft.gui.rendering.entities.feature.properties.MeshedFeature import de.bixilon.minosoft.gui.rendering.entities.renderer.EntityRenderer import de.bixilon.minosoft.gui.rendering.entities.visibility.EntityLayer @@ -32,9 +34,11 @@ open class ItemFeature( renderer: EntityRenderer<*>, stack: ItemStack?, val display: DisplayPositions, + val many: Boolean = true, ) : MeshedFeature(renderer) { private var matrix = Mat4() private var displayMatrix: Mat4 = Mat4.EMPTY_INSTANCE + private var distance: ItemRenderDistance? = null var stack: ItemStack? = stack set(value) { if (field == value) return @@ -48,6 +52,7 @@ open class ItemFeature( override fun update(millis: Long, delta: Float) { if (!_enabled) return unload() + updateDistance() if (this.mesh == null) { val stack = this.stack ?: return unload() createMesh(stack) @@ -55,7 +60,15 @@ open class ItemFeature( updateMatrix() } + private fun updateDistance() { + val distance = ItemRenderDistance.of(renderer.distance) + if (distance == this.distance) return + unload() + this.distance = distance + } + private fun createMesh(stack: ItemStack) { + val distance = this.distance ?: return val model = stack.item.item.getModel(renderer.renderer.connection) ?: return val display = model.getDisplay(display) this.displayMatrix = display?.matrix ?: Mat4.EMPTY_INSTANCE @@ -63,15 +76,17 @@ open class ItemFeature( val tint = renderer.renderer.context.tints.getItemTint(stack) - val count = count(stack.item.count) + val count = if (many) distance.getCount(stack.item.count) else 1 + val spread = maxOf(0.1f, count / 30.0f) + model.render(mesh, stack, tint) // 0 without offset if (count > 1) { val random = Random(1234567890123456789L) for (i in 0 until count - 1) { - mesh.offset.x = random.nextFloat(-0.2f, 0.2f) - mesh.offset.y = random.nextFloat(-0.2f, 0.2f) - mesh.offset.z = random.nextFloat(-0.2f, 0.2f) + mesh.offset.x = random.nextFloat(-spread, spread) + mesh.offset.y = random.nextFloat(-spread, spread) + mesh.offset.z = random.nextFloat(-spread, spread) model.render(mesh, stack, tint) } @@ -81,26 +96,12 @@ open class ItemFeature( this.mesh = mesh } - private fun count(count: Int): Int { - // that is not like vanilla, but imho better - return when { - count <= 0 -> 0 - count == 1 -> 1 - count < 16 -> 2 - count < 32 -> 3 - count < 48 -> 4 - else -> 5 - } - } - private fun updateMatrix() { this.matrix.reset() this.matrix .translateXAssign(-0.5f) .translateZAssign(-0.5f) - // TODO - this.matrix = renderer.matrix * displayMatrix * matrix } @@ -108,6 +109,12 @@ open class ItemFeature( override fun draw(mesh: BlockMesh) { renderer.renderer.context.system.reset(faceCulling = false) val shader = renderer.renderer.features.block.shader + draw(mesh, shader) + } + + + protected open fun draw(mesh: BlockMesh, shader: BlockShader) { + shader.use() shader.matrix = matrix shader.tint = renderer.light.value super.draw(mesh) @@ -115,5 +122,54 @@ open class ItemFeature( override fun unload() { this.displayMatrix = Mat4.EMPTY_INSTANCE + super.unload() + } + + private enum class ItemRenderDistance(distance: Double) { + CLOSE(10.0), + MID(20.0), + FAR(30.0), + EXTREME(48.0), + ; + + val distance = distance * distance + + companion object { + + fun of(distance: Double) = when { + distance < CLOSE.distance -> CLOSE + distance < MID.distance -> MID + distance < FAR.distance -> FAR + distance < EXTREME.distance -> EXTREME + else -> null + } + + fun ItemRenderDistance.getCount(count: Int) = when (this) { + CLOSE -> when { + count <= 16 -> count + else -> 16 + } + + MID -> when { + count <= 4 -> count + count < 16 -> 5 + count < 32 -> 6 + count < 48 -> 7 + else -> 8 + } + + FAR -> when { + count <= 2 -> count + count < 32 -> 3 + else -> 4 + } + + EXTREME -> when { + count <= 1 -> count + count <= 32 -> 1 + else -> 2 + } + } + } } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/renderer/item/ItemEntityRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/renderer/item/ItemEntityRenderer.kt index fbf6f87d6..b707a7afe 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/renderer/item/ItemEntityRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/renderer/item/ItemEntityRenderer.kt @@ -13,6 +13,7 @@ package de.bixilon.minosoft.gui.rendering.entities.renderer.item +import de.bixilon.kutil.math.MathConstants.PIf import de.bixilon.kutil.observer.DataObserver.Companion.observe import de.bixilon.minosoft.data.entities.entities.item.ItemEntity import de.bixilon.minosoft.data.registries.identified.Identified @@ -21,17 +22,42 @@ import de.bixilon.minosoft.gui.rendering.entities.factory.RegisteredEntityModelF import de.bixilon.minosoft.gui.rendering.entities.feature.item.ItemFeature import de.bixilon.minosoft.gui.rendering.entities.renderer.EntityRenderer import de.bixilon.minosoft.gui.rendering.models.raw.display.DisplayPositions +import de.bixilon.minosoft.gui.rendering.util.mat.mat4.Mat4Util.translateYAssign +import kotlin.math.sin class ItemEntityRenderer(renderer: EntitiesRenderer, entity: ItemEntity) : EntityRenderer(renderer, entity) { val item = ItemFeature(this, null, DisplayPositions.GROUND).register() + private var floating = 0.0f + private var rotation = 0.0f init { entity::stack.observe(this, true) { item.stack = it } - // TODO: rotate, lift up and down + } + + override fun update(millis: Long, delta: Float) { + updateFloatingRotation(delta) + super.update(millis, delta) + } + + private fun updateFloatingRotation(delta: Float) { + floating += delta / 3.0f + if (floating > 1.0f) floating %= 1.0f + + rotation += delta / CIRCLE + if (rotation > 1.0f) rotation %= 1.0f + } + + override fun updateMatrix(delta: Float) { + super.updateMatrix(delta) + + this.matrix + .translateYAssign(sin(floating * CIRCLE) * 0.1f + 0.1f) + .rotateYassign(rotation * CIRCLE) } companion object : RegisteredEntityModelFactory, Identified { + const val CIRCLE = PIf * 2.0f override val identifier get() = ItemEntity.identifier override fun create(renderer: EntitiesRenderer, entity: ItemEntity) = ItemEntityRenderer(renderer, entity) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/render/BlockGUIConsumer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/render/BlockGUIConsumer.kt index 402b89bc7..b072039a1 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/render/BlockGUIConsumer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/block/state/render/BlockGUIConsumer.kt @@ -44,10 +44,8 @@ class BlockGUIConsumer( override fun addQuad(offset: FloatArray, positions: FaceVertexData, uvData: FaceVertexData, textureId: Float, lightTint: Float) = Broken("Not chunk rendering") override fun addQuad(positions: FaceVertexData, uvData: FaceVertexData, textureId: Float, lightTint: Float) { - val tint = (lightTint.toBits() shl 8) or 0xFF - gui.context.system.quadOrder.iterateReverse { p, uv -> val vertexOffset = p * Vec3.length val uvOffset = uv * Vec2.length @@ -62,9 +60,6 @@ class BlockGUIConsumer( consumer.addVertex(x, y, textureId, uvData[uvOffset], uvData[uvOffset + 1], tint, options) } - - // block renders from (in normal cases) from 0 to 1 - // matrix should map those pixels into screen 2d space (offset until offset+size) } companion object {