refactor sign block entity renderer + standing back text

To be tested...
This commit is contained in:
Moritz Zwerger 2023-11-02 09:44:41 +01:00
parent 89cc9e63ab
commit d33eb3bb6c
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
2 changed files with 55 additions and 37 deletions

View File

@ -13,10 +13,11 @@
package de.bixilon.minosoft.gui.rendering.chunk.entities.renderer.sign package de.bixilon.minosoft.gui.rendering.chunk.entities.renderer.sign
import de.bixilon.kotlinglm.GLM.PIf
import de.bixilon.kotlinglm.func.rad import de.bixilon.kotlinglm.func.rad
import de.bixilon.kotlinglm.vec2.Vec2 import de.bixilon.kotlinglm.vec2.Vec2
import de.bixilon.kotlinglm.vec3.Vec3 import de.bixilon.kotlinglm.vec3.Vec3
import de.bixilon.kutil.primitive.FloatUtil.toFloat import de.bixilon.kutil.primitive.IntUtil.toInt
import de.bixilon.minosoft.data.Axes import de.bixilon.minosoft.data.Axes
import de.bixilon.minosoft.data.container.stack.ItemStack import de.bixilon.minosoft.data.container.stack.ItemStack
import de.bixilon.minosoft.data.direction.Directions import de.bixilon.minosoft.data.direction.Directions
@ -51,59 +52,62 @@ class SignBlockEntityRenderer(
private fun BlockState.getRotation(): Float { private fun BlockState.getRotation(): Float {
if (this !is PropertyBlockState) return 0.0f if (this !is PropertyBlockState) return 0.0f
val rotation = this.properties[BlockProperties.ROTATION]?.toFloat() ?: return 0.0f val rotation = this.properties[BlockProperties.ROTATION]?.toInt() ?: return 0.0f
return -rotation * ROTATION_STEP return STANDING_ROTATIONS[rotation]
} }
override fun render(position: BlockPosition, offset: FloatArray, mesh: ChunkMeshes, random: Random?, state: BlockState, neighbours: Array<BlockState?>, light: ByteArray, tints: IntArray?, entity: BlockEntity?): Boolean { override fun render(position: BlockPosition, offset: FloatArray, mesh: ChunkMeshes, random: Random?, state: BlockState, neighbours: Array<BlockState?>, light: ByteArray, tints: IntArray?, entity: BlockEntity?): Boolean {
state.model?.render(position, offset, mesh, random, state, neighbours, light, tints, entity) // render wood part state.model?.render(position, offset, mesh, random, state, neighbours, light, tints, entity) // render wood part
if (entity !is SignBlockEntity) return true if (entity !is SignBlockEntity) return true
val light = if (entity.front.glowing) 0xFF else light[SELF_LIGHT_INDEX].toInt()
renderText(state, entity, offset, mesh, light) renderText(state, entity, offset, mesh.textMesh!!, light[SELF_LIGHT_INDEX].toInt())
return true return true
} }
private fun renderText(state: BlockState, entity: SignBlockEntity, offset: FloatArray, mesh: ChunkMeshes, light: Int) { private fun renderText(state: BlockState, sign: SignBlockEntity, offset: FloatArray, mesh: ChunkMesh, light: Int) {
if (state.block is StandingSignBlock) { when (state.block) {
renderStandingText(state.getRotation(), entity, offset, mesh, light) is StandingSignBlock -> renderStandingText(state.getRotation(), sign, offset, mesh, light)
} else if (state.block is WallSignBlock) { is WallSignBlock -> renderWallText(state.getFacing(), sign, offset, mesh, light)
renderWallText(state.getFacing(), entity, offset, mesh, light) // TODO: hanging sign
} }
} }
private fun renderText(offset: FloatArray, entity: SignBlockEntity, rotationVector: Vec3, yRotation: Float, mesh: ChunkMesh, light: Int) { private fun ChunkMesh.ensureSize(text: SignBlockEntity.SignTextProperties) {
val textPosition = offset.toVec3() + rotationVector
// TODO: render back of sign
var primitives = 0 var primitives = 0
for (line in entity.front.text) { for (line in text.text) {
primitives += ChatComponentRenderer.calculatePrimitiveCount(line) primitives += ChatComponentRenderer.calculatePrimitiveCount(line)
} }
mesh.data.ensureSize(primitives * mesh.order.size * ChunkMesh.ChunkMeshStruct.FLOATS_PER_VERTEX) data.ensureSize(primitives * order.size * ChunkMesh.ChunkMeshStruct.FLOATS_PER_VERTEX)
}
private fun renderText(offset: FloatArray, text: SignBlockEntity.SignTextProperties, blockOffset: Vec3, yRotation: Float, mesh: ChunkMesh, light: Int) {
val textPosition = offset.toVec3() + blockOffset
val light = if (text.glowing) 0xFF else light
val rotation = Vec3(0.0f, -yRotation, 0.0f)
val alignment = context.connection.profiles.block.rendering.entities.sign.fontAlignment val alignment = context.connection.profiles.block.rendering.entities.sign.fontAlignment
val properties = if (alignment == TEXT_PROPERTIES.alignment) TEXT_PROPERTIES else TEXT_PROPERTIES.copy(alignment = alignment) val properties = if (alignment == TEXT_PROPERTIES.alignment) TEXT_PROPERTIES else TEXT_PROPERTIES.copy(alignment = alignment)
for (line in entity.front.text) { mesh.ensureSize(text)
ChatComponentRenderer.render3dFlat(context, textPosition, properties, Vec3(0.0f, -yRotation, 0.0f), MAX_SIZE, mesh, line, light)
textPosition.y -= 0.11f for (line in text.text) {
ChatComponentRenderer.render3dFlat(context, textPosition, properties, rotation, MAX_SIZE, mesh, line, light)
textPosition.y -= LINE_HEIGHT
} }
} }
private fun renderStandingText(rotation: Float, entity: SignBlockEntity, offset: FloatArray, mesh: ChunkMeshes, light: Int) { private fun renderStandingText(rotation: Float, sign: SignBlockEntity, offset: FloatArray, mesh: ChunkMesh, light: Int) {
val rotationVector = Vec3(X_OFFSET, 17.5f / BLOCK_SIZE - Y_OFFSET, 9.0f / BLOCK_SIZE + Z_OFFSET) val frontOffset = Vec3(STANDING_FRONT_OFFSET).apply { signRotate(rotation) }
rotationVector.signRotate(rotation.rad) renderText(offset, sign.front, frontOffset, rotation, mesh, light)
renderText(offset, entity, rotationVector, rotation, mesh.textMesh!!, light) val backOffset = Vec3(STANDING_BACK_OFFSET).apply { signRotate(rotation) }
renderText(offset, sign.back, backOffset, rotation, mesh, light)
} }
private fun renderWallText(facing: Directions, entity: SignBlockEntity, position: FloatArray, mesh: ChunkMeshes, light: Int) { private fun renderWallText(facing: Directions, sign: SignBlockEntity, offset: FloatArray, mesh: ChunkMesh, light: Int) {
val yRotation = ROTATIONS[facing.ordinal - Directions.SIDE_OFFSET] val rotation = WALL_ROTATIONS[facing.ordinal - Directions.SIDE_OFFSET]
val rotationVector = Vec3(X_OFFSET, 12.5f / BLOCK_SIZE - Y_OFFSET, 2.0f / BLOCK_SIZE + Z_OFFSET) val blockOffset = Vec3(WALL_OFFSET).apply { signRotate(rotation) }
rotationVector.signRotate(yRotation.rad)
renderText(position, entity, rotationVector, yRotation, mesh.textMesh!!, light) renderText(offset, sign.front, blockOffset, rotation, mesh, light)
} }
private fun Vec3.signRotate(yRotation: Float) { private fun Vec3.signRotate(yRotation: Float) {
@ -116,15 +120,29 @@ class SignBlockEntityRenderer(
companion object { companion object {
private val TEXT_PROPERTIES = TextRenderProperties(scale = 1.35f, allowNewLine = false, shadow = false, fallbackColor = ChatColors.BLACK) private val TEXT_PROPERTIES = TextRenderProperties(scale = 1.35f, allowNewLine = false, shadow = false, fallbackColor = ChatColors.BLACK)
private const val PIXEL_SCALE = 1.0f / ChatComponentRenderer.TEXT_BLOCK_RESOLUTION
private const val Z_OFFSET = 0.01f private const val Z_OFFSET = 0.01f
private const val X_OFFSET = PIXEL_SCALE * 6
private const val Y_OFFSET = 0.04f
private const val ROTATION_STEP = 22.5f
const val SIGN_MAX_WIDTH = 90 // 15x the char W. W has a width of 5sp const val SIGN_MAX_WIDTH = 90 // 15x the char W. W has a width of 5sp
val MAX_SIZE = Vec2(SIGN_MAX_WIDTH * TEXT_PROPERTIES.scale, TEXT_PROPERTIES.lineHeight) val MAX_SIZE = Vec2(SIGN_MAX_WIDTH * TEXT_PROPERTIES.scale, TEXT_PROPERTIES.lineHeight)
private val ROTATIONS = floatArrayOf(180.0f, 0.0f, 90.0f, 270.0f) const val SIGN_BOARD_HEIGHT = 8.0f / BLOCK_SIZE
const val SIGN_BOARD_MARGIN = SIGN_BOARD_HEIGHT / 10.0f
const val LINE_HEIGHT = (SIGN_BOARD_HEIGHT - (2 * SIGN_BOARD_MARGIN)) / SignBlockEntity.LINES
const val STANDING_ROTATION_STEPS = 16
val STANDING_ROTATIONS = FloatArray(STANDING_ROTATION_STEPS) { -it * (2 * PIf) / STANDING_ROTATION_STEPS }
const val STANDING_BOARD_HEIGHT = 17.5f / BLOCK_SIZE
const val STANDING_FRONT_DISTANCE = 9.0f / BLOCK_SIZE
const val STANDING_BACK_DISTANCE = 7.0f / BLOCK_SIZE
val STANDING_FRONT_OFFSET = Vec3(SIGN_BOARD_MARGIN, STANDING_BOARD_HEIGHT - SIGN_BOARD_MARGIN, STANDING_FRONT_DISTANCE + Z_OFFSET)
val STANDING_BACK_OFFSET = Vec3(BLOCK_SIZE - SIGN_BOARD_MARGIN, STANDING_BOARD_HEIGHT - SIGN_BOARD_MARGIN, STANDING_BACK_DISTANCE + Z_OFFSET)
val WALL_ROTATIONS = floatArrayOf(180.0f.rad, 0.0f, 90.0f.rad, 270.0f.rad)
const val WALL_HEIGHT = 12.5f / BLOCK_SIZE
const val WALL_DISTANCE = 2.0f / BLOCK_SIZE
val WALL_OFFSET = Vec3(SIGN_BOARD_MARGIN, WALL_HEIGHT - SIGN_BOARD_MARGIN, WALL_DISTANCE + Z_OFFSET)
} }
} }

View File

@ -29,7 +29,7 @@ import de.bixilon.minosoft.gui.rendering.font.renderer.element.TextRenderInfo
import de.bixilon.minosoft.gui.rendering.font.renderer.element.TextRenderProperties import de.bixilon.minosoft.gui.rendering.font.renderer.element.TextRenderProperties
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
import de.bixilon.minosoft.gui.rendering.util.mat.mat4.Mat4Util.rotateDegreesAssign import de.bixilon.minosoft.gui.rendering.util.mat.mat4.Mat4Util.rotateRadAssign
interface ChatComponentRenderer<T : ChatComponent> { interface ChatComponentRenderer<T : ChatComponent> {
@ -55,7 +55,7 @@ interface ChatComponentRenderer<T : ChatComponent> {
fun render3dFlat(context: RenderContext, position: Vec3, properties: TextRenderProperties, rotation: Vec3, maxSize: Vec2, mesh: ChunkMesh, text: ChatComponent, light: Int): TextRenderInfo { fun render3dFlat(context: RenderContext, position: Vec3, properties: TextRenderProperties, rotation: Vec3, maxSize: Vec2, mesh: ChunkMesh, text: ChatComponent, light: Int): TextRenderInfo {
val matrix = Mat4() val matrix = Mat4()
.translateAssign(position) .translateAssign(position)
.rotateDegreesAssign(rotation) .rotateRadAssign(rotation)
.translateAssign(Vec3(0, 0, -1)) .translateAssign(Vec3(0, 0, -1))
val primitives = calculatePrimitiveCount(text) val primitives = calculatePrimitiveCount(text)