item rendering fixes, item item rotation and floating

This commit is contained in:
Moritz Zwerger 2023-11-15 22:21:47 +01:00
parent 80f4bd1286
commit 66f960a28d
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
3 changed files with 101 additions and 24 deletions

View File

@ -17,6 +17,8 @@ import de.bixilon.kotlinglm.mat4x4.Mat4
import de.bixilon.kutil.random.RandomUtil.nextFloat import de.bixilon.kutil.random.RandomUtil.nextFloat
import de.bixilon.minosoft.data.container.stack.ItemStack 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.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.feature.properties.MeshedFeature
import de.bixilon.minosoft.gui.rendering.entities.renderer.EntityRenderer import de.bixilon.minosoft.gui.rendering.entities.renderer.EntityRenderer
import de.bixilon.minosoft.gui.rendering.entities.visibility.EntityLayer import de.bixilon.minosoft.gui.rendering.entities.visibility.EntityLayer
@ -32,9 +34,11 @@ open class ItemFeature(
renderer: EntityRenderer<*>, renderer: EntityRenderer<*>,
stack: ItemStack?, stack: ItemStack?,
val display: DisplayPositions, val display: DisplayPositions,
val many: Boolean = true,
) : MeshedFeature<BlockMesh>(renderer) { ) : MeshedFeature<BlockMesh>(renderer) {
private var matrix = Mat4() private var matrix = Mat4()
private var displayMatrix: Mat4 = Mat4.EMPTY_INSTANCE private var displayMatrix: Mat4 = Mat4.EMPTY_INSTANCE
private var distance: ItemRenderDistance? = null
var stack: ItemStack? = stack var stack: ItemStack? = stack
set(value) { set(value) {
if (field == value) return if (field == value) return
@ -48,6 +52,7 @@ open class ItemFeature(
override fun update(millis: Long, delta: Float) { override fun update(millis: Long, delta: Float) {
if (!_enabled) return unload() if (!_enabled) return unload()
updateDistance()
if (this.mesh == null) { if (this.mesh == null) {
val stack = this.stack ?: return unload() val stack = this.stack ?: return unload()
createMesh(stack) createMesh(stack)
@ -55,7 +60,15 @@ open class ItemFeature(
updateMatrix() updateMatrix()
} }
private fun updateDistance() {
val distance = ItemRenderDistance.of(renderer.distance)
if (distance == this.distance) return
unload()
this.distance = distance
}
private fun createMesh(stack: ItemStack) { private fun createMesh(stack: ItemStack) {
val distance = this.distance ?: return
val model = stack.item.item.getModel(renderer.renderer.connection) ?: return val model = stack.item.item.getModel(renderer.renderer.connection) ?: return
val display = model.getDisplay(display) val display = model.getDisplay(display)
this.displayMatrix = display?.matrix ?: Mat4.EMPTY_INSTANCE this.displayMatrix = display?.matrix ?: Mat4.EMPTY_INSTANCE
@ -63,15 +76,17 @@ open class ItemFeature(
val tint = renderer.renderer.context.tints.getItemTint(stack) 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 model.render(mesh, stack, tint) // 0 without offset
if (count > 1) { if (count > 1) {
val random = Random(1234567890123456789L) val random = Random(1234567890123456789L)
for (i in 0 until count - 1) { for (i in 0 until count - 1) {
mesh.offset.x = random.nextFloat(-0.2f, 0.2f) mesh.offset.x = random.nextFloat(-spread, spread)
mesh.offset.y = random.nextFloat(-0.2f, 0.2f) mesh.offset.y = random.nextFloat(-spread, spread)
mesh.offset.z = random.nextFloat(-0.2f, 0.2f) mesh.offset.z = random.nextFloat(-spread, spread)
model.render(mesh, stack, tint) model.render(mesh, stack, tint)
} }
@ -81,26 +96,12 @@ open class ItemFeature(
this.mesh = mesh 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() { private fun updateMatrix() {
this.matrix.reset() this.matrix.reset()
this.matrix this.matrix
.translateXAssign(-0.5f) .translateXAssign(-0.5f)
.translateZAssign(-0.5f) .translateZAssign(-0.5f)
// TODO
this.matrix = renderer.matrix * displayMatrix * matrix this.matrix = renderer.matrix * displayMatrix * matrix
} }
@ -108,6 +109,12 @@ open class ItemFeature(
override fun draw(mesh: BlockMesh) { override fun draw(mesh: BlockMesh) {
renderer.renderer.context.system.reset(faceCulling = false) renderer.renderer.context.system.reset(faceCulling = false)
val shader = renderer.renderer.features.block.shader val shader = renderer.renderer.features.block.shader
draw(mesh, shader)
}
protected open fun draw(mesh: BlockMesh, shader: BlockShader) {
shader.use()
shader.matrix = matrix shader.matrix = matrix
shader.tint = renderer.light.value shader.tint = renderer.light.value
super.draw(mesh) super.draw(mesh)
@ -115,5 +122,54 @@ open class ItemFeature(
override fun unload() { override fun unload() {
this.displayMatrix = Mat4.EMPTY_INSTANCE 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
}
}
}
} }
} }

View File

@ -13,6 +13,7 @@
package de.bixilon.minosoft.gui.rendering.entities.renderer.item 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.kutil.observer.DataObserver.Companion.observe
import de.bixilon.minosoft.data.entities.entities.item.ItemEntity import de.bixilon.minosoft.data.entities.entities.item.ItemEntity
import de.bixilon.minosoft.data.registries.identified.Identified 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.feature.item.ItemFeature
import de.bixilon.minosoft.gui.rendering.entities.renderer.EntityRenderer 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.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<ItemEntity>(renderer, entity) { class ItemEntityRenderer(renderer: EntitiesRenderer, entity: ItemEntity) : EntityRenderer<ItemEntity>(renderer, entity) {
val item = ItemFeature(this, null, DisplayPositions.GROUND).register() val item = ItemFeature(this, null, DisplayPositions.GROUND).register()
private var floating = 0.0f
private var rotation = 0.0f
init { init {
entity::stack.observe(this, true) { item.stack = it } 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<ItemEntity>, Identified { companion object : RegisteredEntityModelFactory<ItemEntity>, Identified {
const val CIRCLE = PIf * 2.0f
override val identifier get() = ItemEntity.identifier override val identifier get() = ItemEntity.identifier
override fun create(renderer: EntitiesRenderer, entity: ItemEntity) = ItemEntityRenderer(renderer, entity) override fun create(renderer: EntitiesRenderer, entity: ItemEntity) = ItemEntityRenderer(renderer, entity)

View File

@ -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(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) { override fun addQuad(positions: FaceVertexData, uvData: FaceVertexData, textureId: Float, lightTint: Float) {
val tint = (lightTint.toBits() shl 8) or 0xFF val tint = (lightTint.toBits() shl 8) or 0xFF
gui.context.system.quadOrder.iterateReverse { p, uv -> gui.context.system.quadOrder.iterateReverse { p, uv ->
val vertexOffset = p * Vec3.length val vertexOffset = p * Vec3.length
val uvOffset = uv * Vec2.length val uvOffset = uv * Vec2.length
@ -62,9 +60,6 @@ class BlockGUIConsumer(
consumer.addVertex(x, y, textureId, uvData[uvOffset], uvData[uvOffset + 1], tint, options) 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 { companion object {