diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/Registry.kt b/src/main/java/de/bixilon/minosoft/data/mappings/Registry.kt index 824c2c82d..d12941191 100644 --- a/src/main/java/de/bixilon/minosoft/data/mappings/Registry.kt +++ b/src/main/java/de/bixilon/minosoft/data/mappings/Registry.kt @@ -31,8 +31,8 @@ open class Registry( return resourceLocationMap[resourceLocation] ?: parentRegistry?.get(resourceLocation) } - open fun get(id: Int): T? { - return idMap[id] ?: parentRegistry?.get(id) + open fun get(id: Int): T { + return idMap[id] ?: parentRegistry?.get(id)!! } open fun getId(value: T): Int { diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/blocks/Block.kt b/src/main/java/de/bixilon/minosoft/data/mappings/blocks/Block.kt index 642712f82..4dac4e174 100644 --- a/src/main/java/de/bixilon/minosoft/data/mappings/blocks/Block.kt +++ b/src/main/java/de/bixilon/minosoft/data/mappings/blocks/Block.kt @@ -34,7 +34,7 @@ data class Block( val states: MutableSet = mutableSetOf() override fun postInit(versionMapping: VersionMapping) { - item = versionMapping.itemRegistry.get(itemId)!! + item = versionMapping.itemRegistry.get(itemId) } companion object : ResourceLocationDeserializer { diff --git a/src/main/java/de/bixilon/minosoft/data/mappings/items/ItemRegistry.kt b/src/main/java/de/bixilon/minosoft/data/mappings/items/ItemRegistry.kt index 4bcdef1af..d8bd0e86b 100644 --- a/src/main/java/de/bixilon/minosoft/data/mappings/items/ItemRegistry.kt +++ b/src/main/java/de/bixilon/minosoft/data/mappings/items/ItemRegistry.kt @@ -26,7 +26,7 @@ class ItemRegistry( ) : Registry(parentRegistry = parentRegistry, initialSize = initialSize) { private var flattened = false - override fun get(id: Int): Item? { + override fun get(id: Int): Item { return if (!flattened) { val itemId = id ushr 16 val itemMeta = id and 0xFFFF @@ -35,7 +35,11 @@ class ItemRegistry( if (itemMeta > 0 && itemMeta < Short.MAX_VALUE) { versionItemId = versionItemId or itemMeta } - return super.get(versionItemId) ?: super.get(itemId shl 16) // ignore meta data ? + return try { + super.get(versionItemId) + } catch (exception: NullPointerException) { + super.get(itemId shl 16) // ignore meta data ? + } } else { super.get(id) } diff --git a/src/main/java/de/bixilon/minosoft/data/text/BaseComponent.java b/src/main/java/de/bixilon/minosoft/data/text/BaseComponent.java index 1204a43df..522bd8e21 100644 --- a/src/main/java/de/bixilon/minosoft/data/text/BaseComponent.java +++ b/src/main/java/de/bixilon/minosoft/data/text/BaseComponent.java @@ -21,6 +21,7 @@ import de.bixilon.minosoft.data.locale.minecraft.MinecraftLocaleManager; import de.bixilon.minosoft.gui.rendering.font.Font; import de.bixilon.minosoft.gui.rendering.font.FontBindings; import de.bixilon.minosoft.gui.rendering.hud.HUDScale; +import de.bixilon.minosoft.gui.rendering.hud.elements.text.HUDFontMesh; import de.bixilon.minosoft.modding.event.events.annotations.Unsafe; import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition; import de.bixilon.minosoft.util.hash.BetterHashSet; @@ -33,7 +34,6 @@ import javax.annotation.Nullable; import java.text.CharacterIterator; import java.text.StringCharacterIterator; import java.util.ArrayList; -import java.util.List; public class BaseComponent extends ChatComponent { private static final String LEGACY_RESET_SUFFIX = String.valueOf(ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR) + PostChatFormattingCodes.RESET.getChar(); @@ -215,14 +215,14 @@ public class BaseComponent extends ChatComponent { } @Override - public void addVerticies(Vec2 startPosition, Vec2 offset, Mat4 perspectiveMatrix, FontBindings binding, Font font, HUDScale hudScale, List meshData, Vec2 maxSize) { + public void addVerticies(Vec2 startPosition, Vec2 offset, Mat4 perspectiveMatrix, FontBindings binding, Font font, HUDScale hudScale, HUDFontMesh mesh, Vec2 maxSize) { if (binding == FontBindings.RIGHT_DOWN || binding == FontBindings.RIGHT_UP) { for (int i = this.parts.size() - 1; i >= 0; i--) { - this.parts.get(i).addVerticies(startPosition, offset, perspectiveMatrix, binding, font, hudScale, meshData, maxSize); + this.parts.get(i).addVerticies(startPosition, offset, perspectiveMatrix, binding, font, hudScale, mesh, maxSize); } } else { for (var chatPart : this.parts) { - chatPart.addVerticies(startPosition, offset, perspectiveMatrix, binding, font, hudScale, meshData, maxSize); + chatPart.addVerticies(startPosition, offset, perspectiveMatrix, binding, font, hudScale, mesh, maxSize); } } } diff --git a/src/main/java/de/bixilon/minosoft/data/text/ChatComponent.java b/src/main/java/de/bixilon/minosoft/data/text/ChatComponent.java index 88396a808..8775a797b 100644 --- a/src/main/java/de/bixilon/minosoft/data/text/ChatComponent.java +++ b/src/main/java/de/bixilon/minosoft/data/text/ChatComponent.java @@ -21,6 +21,7 @@ import de.bixilon.minosoft.data.locale.minecraft.MinecraftLocaleManager; import de.bixilon.minosoft.gui.rendering.font.Font; import de.bixilon.minosoft.gui.rendering.font.FontBindings; import de.bixilon.minosoft.gui.rendering.hud.HUDScale; +import de.bixilon.minosoft.gui.rendering.hud.elements.text.HUDFontMesh; import glm_.mat4x4.Mat4; import glm_.vec2.Vec2; import javafx.collections.FXCollections; @@ -28,7 +29,6 @@ import javafx.collections.ObservableList; import javafx.scene.Node; import javax.annotation.Nullable; -import java.util.List; public abstract class ChatComponent { public static ChatComponent valueOf(Object raw) { @@ -96,5 +96,5 @@ public abstract class ChatComponent { /** * @return Adds all verticies to the array (used in opengl) */ - public abstract void addVerticies(Vec2 startPosition, Vec2 offset, Mat4 perspectiveMatrix, FontBindings binding, Font font, HUDScale hudScale, List meshData, Vec2 maxSize); + public abstract void addVerticies(Vec2 startPosition, Vec2 offset, Mat4 perspectiveMatrix, FontBindings binding, Font font, HUDScale hudScale, HUDFontMesh mesh, Vec2 maxSize); } diff --git a/src/main/java/de/bixilon/minosoft/data/text/TextComponent.kt b/src/main/java/de/bixilon/minosoft/data/text/TextComponent.kt index c581a9eee..a020bcf8f 100644 --- a/src/main/java/de/bixilon/minosoft/data/text/TextComponent.kt +++ b/src/main/java/de/bixilon/minosoft/data/text/TextComponent.kt @@ -17,11 +17,13 @@ import de.bixilon.minosoft.gui.rendering.font.Font import de.bixilon.minosoft.gui.rendering.font.FontBindings import de.bixilon.minosoft.gui.rendering.font.FontChar import de.bixilon.minosoft.gui.rendering.hud.HUDScale +import de.bixilon.minosoft.gui.rendering.hud.elements.text.HUDFontMesh import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition import de.bixilon.minosoft.util.Util import de.bixilon.minosoft.util.hash.BetterHashSet import glm_.mat4x4.Mat4 import glm_.vec2.Vec2 +import glm_.vec3.Vec3 import glm_.vec4.Vec4 import javafx.animation.Animation import javafx.animation.KeyFrame @@ -201,25 +203,20 @@ open class TextComponent : ChatComponent { return nodes } - override fun addVerticies(startPosition: Vec2, offset: Vec2, perspectiveMatrix: Mat4, binding: FontBindings, font: Font, hudScale: HUDScale, meshData: MutableList, maxSize: Vec2) { - fun drawLetterVertex(position: Vec2, uv: Vec2, atlasPage: Int, color: RGBColor, meshData: MutableList) { + override fun addVerticies(startPosition: Vec2, offset: Vec2, perspectiveMatrix: Mat4, binding: FontBindings, font: Font, hudScale: HUDScale, mesh: HUDFontMesh, maxSize: Vec2) { + + fun drawLetterVertex(position: Vec3, uv: Vec2, atlasPage: Int) { val matrixPosition = perspectiveMatrix * Vec4(position.x, position.y, 0f, 1f) - meshData.add(matrixPosition.x) - meshData.add(matrixPosition.y) - meshData.add(-0.997f) - meshData.add(uv.x) - meshData.add(uv.y) - meshData.add(Float.fromBits(atlasPage)) - meshData.add(Float.fromBits(color.color)) + mesh.addVertex(Vec3(matrixPosition.x, matrixPosition.y, position.z), uv, atlasPage, color) } - fun drawLetter(position: Vec2, scaledWidth: Float, scaledHeight: Float, fontChar: FontChar, color: RGBColor, meshData: MutableList) { - drawLetterVertex(Vec2(position.x, position.y), fontChar.texturePosition[texturePositionCoordinates[binding.ordinal][0]], fontChar.atlasTextureIndex, color, meshData) - drawLetterVertex(Vec2(position.x, position.y + scaledHeight), fontChar.texturePosition[texturePositionCoordinates[binding.ordinal][3]], fontChar.atlasTextureIndex, color, meshData) - drawLetterVertex(Vec2(position.x + scaledWidth, position.y), fontChar.texturePosition[texturePositionCoordinates[binding.ordinal][1]], fontChar.atlasTextureIndex, color, meshData) - drawLetterVertex(Vec2(position.x + scaledWidth, position.y), fontChar.texturePosition[texturePositionCoordinates[binding.ordinal][1]], fontChar.atlasTextureIndex, color, meshData) - drawLetterVertex(Vec2(position.x, position.y + scaledHeight), fontChar.texturePosition[texturePositionCoordinates[binding.ordinal][3]], fontChar.atlasTextureIndex, color, meshData) - drawLetterVertex(Vec2(position.x + scaledWidth, position.y + scaledHeight), fontChar.texturePosition[texturePositionCoordinates[binding.ordinal][2]], fontChar.atlasTextureIndex, color, meshData) + fun drawLetter(position: Vec2, scaledWidth: Float, scaledHeight: Float, fontChar: FontChar) { + drawLetterVertex(Vec3(position.x, position.y, HUD_Z_COORDINATE), fontChar.texturePosition[texturePositionCoordinates[binding.ordinal][0]], fontChar.atlasTextureIndex) + drawLetterVertex(Vec3(position.x, position.y + scaledHeight, HUD_Z_COORDINATE), fontChar.texturePosition[texturePositionCoordinates[binding.ordinal][3]], fontChar.atlasTextureIndex) + drawLetterVertex(Vec3(position.x + scaledWidth, position.y, HUD_Z_COORDINATE), fontChar.texturePosition[texturePositionCoordinates[binding.ordinal][1]], fontChar.atlasTextureIndex) + drawLetterVertex(Vec3(position.x + scaledWidth, position.y, HUD_Z_COORDINATE), fontChar.texturePosition[texturePositionCoordinates[binding.ordinal][1]], fontChar.atlasTextureIndex) + drawLetterVertex(Vec3(position.x, position.y + scaledHeight, HUD_Z_COORDINATE), fontChar.texturePosition[texturePositionCoordinates[binding.ordinal][3]], fontChar.atlasTextureIndex) + drawLetterVertex(Vec3(position.x + scaledWidth, position.y + scaledHeight, HUD_Z_COORDINATE), fontChar.texturePosition[texturePositionCoordinates[binding.ordinal][2]], fontChar.atlasTextureIndex) } // reverse text if right bound val charArray = when (binding) { @@ -260,7 +257,7 @@ open class TextComponent : ChatComponent { } val fontChar = font.getChar(char) val scaledX = fontChar.width * (font.charHeight / fontChar.height.toFloat()) * hudScale.scale - drawLetter(startPosition + offset, scaledX, scaledHeight, fontChar, color, meshData) + drawLetter(startPosition + offset, scaledX, scaledHeight, fontChar) offset += Vec2(scaledX + (hudScale.scale / 2), 0f) if (offset.x >= maxSize.x) { maxSize.x += scaledX + (hudScale.scale / 2) @@ -280,5 +277,7 @@ open class TextComponent : ChatComponent { listOf(2, 3, 0, 1), listOf(3, 2, 1, 0), ) // matches FontBindings::ordinal + + const val HUD_Z_COORDINATE = -0.997f } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/WorldMesh.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkMesh.kt similarity index 63% rename from src/main/java/de/bixilon/minosoft/gui/rendering/chunk/WorldMesh.kt rename to src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkMesh.kt index 018481fde..6a2adc4d6 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/WorldMesh.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkMesh.kt @@ -13,22 +13,51 @@ package de.bixilon.minosoft.gui.rendering.chunk +import de.bixilon.minosoft.data.text.RGBColor +import de.bixilon.minosoft.gui.rendering.textures.Texture import glm_.BYTES +import glm_.vec2.Vec2 +import glm_.vec3.Vec3 import org.lwjgl.opengl.GL11.GL_FLOAT import org.lwjgl.opengl.GL20.glEnableVertexAttribArray import org.lwjgl.opengl.GL20.glVertexAttribPointer import org.lwjgl.opengl.GL30.* -class WorldMesh(data: FloatArray) { - var vAO: Int = glGenVertexArrays() - var vBO: Int = glGenBuffers() - var trianglesCount: Int = data.size / FLOATS_PER_VERTEX +class ChunkMesh { + private val data: MutableList = mutableListOf() + private var vao: Int = 0 + private var vbo: Int = 0 + private var trianglesCount: Int = 0 + + fun addVertex(position: Vec3, textureCoordinates: Vec2, texture: Texture, tintColor: RGBColor?) { + data.add(position.x) + data.add(position.y) + data.add(position.z) + data.add(textureCoordinates.x * texture.widthFactor) + data.add(textureCoordinates.y * texture.heightFactor) + data.add(Float.fromBits(texture.id)) // ToDo: Compact this + + // ToDo: Send this only once per texture + data.add(texture.animationFrameTime.toFloat()) + data.add(texture.animations.toFloat()) + data.add(texture.heightFactor) + + if (tintColor == null) { + data.add(0f) + } else { + data.add(Float.fromBits(tintColor.color)) + } + } + + fun load() { + trianglesCount = data.size / FLOATS_PER_VERTEX + vao = glGenVertexArrays() + vbo = glGenBuffers() - init { // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s). - glBindVertexArray(vAO) - glBindBuffer(GL_ARRAY_BUFFER, vBO) - glBufferData(GL_ARRAY_BUFFER, data, GL_STATIC_DRAW) + glBindVertexArray(vao) + glBindBuffer(GL_ARRAY_BUFFER, vbo) + glBufferData(GL_ARRAY_BUFFER, data.toFloatArray(), GL_STATIC_DRAW) var index = 0 glVertexAttribPointer(index, 3, GL_FLOAT, false, FLOATS_PER_VERTEX * Float.BYTES, 0L) glEnableVertexAttribArray(index++) @@ -53,13 +82,13 @@ class WorldMesh(data: FloatArray) { } fun draw() { - glBindVertexArray(vAO) + glBindVertexArray(vao) glDrawArrays(GL_TRIANGLES, 0, trianglesCount) } fun unload() { - glDeleteVertexArrays(vAO) - glDeleteBuffers(vBO) + glDeleteVertexArrays(vao) + glDeleteBuffers(vbo) } companion object { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkRenderer.kt index afb7472c1..6927bf0fc 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/ChunkRenderer.kt @@ -36,12 +36,12 @@ import java.util.concurrent.ConcurrentHashMap class ChunkRenderer(private val connection: Connection, private val world: World, val renderWindow: RenderWindow) : Renderer { private lateinit var minecraftTextures: TextureArray lateinit var chunkShader: Shader - private val chunkSectionsToDraw = ConcurrentHashMap>() + private val chunkSectionsToDraw = ConcurrentHashMap>() private var currentTick = 0 // for animation usage private var lastTickIncrementTime = 0L - private fun prepareChunk(chunkLocation: ChunkLocation, sectionHeight: Int, section: ChunkSection, chunk: Chunk): FloatArray { - val data: MutableList = mutableListOf() + private fun prepareChunk(chunkLocation: ChunkLocation, sectionHeight: Int, section: ChunkSection, chunk: Chunk): ChunkMesh { + val mesh = ChunkMesh() val below = world.allChunks[chunkLocation]?.sections?.get(sectionHeight - 1) val above = world.allChunks[chunkLocation]?.sections?.get(sectionHeight + 1) @@ -108,9 +108,9 @@ class ChunkRenderer(private val connection: Connection, private val world: World blockInfo.block.tintColor?.let { tintColor = it } } - blockInfo.block.getBlockRenderer(blockPosition).render(blockInfo, tintColor, worldPosition, data, arrayOf(blockBelow, blockAbove, blockNorth, blockSouth, blockWest, blockEast)) + blockInfo.block.getBlockRenderer(blockPosition).render(blockInfo, tintColor, worldPosition, mesh, arrayOf(blockBelow, blockAbove, blockNorth, blockSouth, blockWest, blockEast)) } - return data.toFloatArray() + return mesh } override fun init() { @@ -170,7 +170,7 @@ class ChunkRenderer(private val connection: Connection, private val world: World fun prepareChunkSection(chunkLocation: ChunkLocation, sectionHeight: Int, section: ChunkSection, chunk: Chunk) { renderWindow.rendering.executor.execute { - val data = prepareChunk(chunkLocation, sectionHeight, section, chunk) + val mesh = prepareChunk(chunkLocation, sectionHeight, section, chunk) var sectionMap = chunkSectionsToDraw[chunkLocation] if (sectionMap == null) { @@ -178,9 +178,9 @@ class ChunkRenderer(private val connection: Connection, private val world: World chunkSectionsToDraw[chunkLocation] = sectionMap } renderWindow.renderQueue.add { - val newMesh = WorldMesh(data) + mesh.load() sectionMap[sectionHeight]?.unload() - sectionMap[sectionHeight] = newMesh + sectionMap[sectionHeight] = mesh } } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/renderable/BlockRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/renderable/BlockRenderer.kt index 9b27aacc2..574acef44 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/renderable/BlockRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/renderable/BlockRenderer.kt @@ -17,6 +17,7 @@ import com.google.gson.JsonObject import de.bixilon.minosoft.data.Directions import de.bixilon.minosoft.data.text.RGBColor import de.bixilon.minosoft.data.world.BlockInfo +import de.bixilon.minosoft.gui.rendering.chunk.ChunkMesh import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModel import de.bixilon.minosoft.gui.rendering.textures.Texture import glm_.mat4x4.Mat4 @@ -69,7 +70,7 @@ class BlockRenderer(data: JsonObject, parent: BlockModel) { } } - fun render(blockInfo: BlockInfo, tintColor: RGBColor?, position: Vec3, data: MutableList, neighbourBlocks: Array) { + fun render(blockInfo: BlockInfo, tintColor: RGBColor?, position: Vec3, mesh: ChunkMesh, neighbourBlocks: Array) { val modelMatrix = Mat4().translate(position) for (direction in Directions.DIRECTIONS) { @@ -90,7 +91,7 @@ class BlockRenderer(data: JsonObject, parent: BlockModel) { continue } - element.render(tintColor, textureMapping, modelMatrix, direction, data) + element.render(tintColor, textureMapping, modelMatrix, direction, mesh) } } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/renderable/ElementRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/renderable/ElementRenderer.kt index f3423eac8..75e257dbe 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/renderable/ElementRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/models/renderable/ElementRenderer.kt @@ -17,6 +17,7 @@ import com.google.gson.JsonObject import de.bixilon.minosoft.data.Axes import de.bixilon.minosoft.data.Directions import de.bixilon.minosoft.data.text.RGBColor +import de.bixilon.minosoft.gui.rendering.chunk.ChunkMesh import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModel import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModelElement import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModelFace @@ -28,7 +29,7 @@ import glm_.vec2.Vec2 import glm_.vec3.Vec3 import glm_.vec4.Vec4 -class ElementRenderer(element: BlockModelElement, rotation: Vec3, uvlock: Boolean, rescale: Boolean) { +class ElementRenderer(element: BlockModelElement, rotation: Vec3, uvLock: Boolean, rescale: Boolean) { private val fullFaceDirections: MutableSet = mutableSetOf() private val faces: MutableMap = HashMap(element.faces) private var positions: Array = element.positions.clone() @@ -49,7 +50,7 @@ class ElementRenderer(element: BlockModelElement, rotation: Vec3, uvlock: Boolea } - fun render(tintColor: RGBColor?, textureMapping: MutableMap, modelMatrix: Mat4, direction: Directions, data: MutableList) { + fun render(tintColor: RGBColor?, textureMapping: MutableMap, modelMatrix: Mat4, direction: Directions, mesh: ChunkMesh) { val realDirection = directionMapping[direction]!! val positionTemplate = BlockModelElement.FACE_POSITION_MAP_TEMPLATE[realDirection.ordinal] @@ -61,31 +62,21 @@ class ElementRenderer(element: BlockModelElement, rotation: Vec3, uvlock: Boolea val drawPositions = arrayOf(positions[positionTemplate[0]], positions[positionTemplate[1]], positions[positionTemplate[2]], positions[positionTemplate[3]]) - fun addToData(vec3: Vec3, textureCoordinates: Vec2) { - val input = Vec4(vec3, 1.0f) - val output = modelMatrix * input - data.add(output.x) - data.add(output.y) - data.add(output.z) - data.add(textureCoordinates.x * texture.widthFactor) - data.add(textureCoordinates.y * texture.heightFactor) - data.add(Float.fromBits(texture.id)) // ToDo: Compact this - - // ToDo: Send this only once per texture - data.add(texture.animationFrameTime.toFloat()) - data.add(texture.animations.toFloat()) - data.add(texture.heightFactor) - - if (face.tint && tintColor != null) { - data.add(Float.fromBits(tintColor.color)) - } else { - data.add(0f) - } - } fun createQuad(drawPositions: Array, texturePositions: Array) { for (vertex in drawOrder) { - addToData(drawPositions[vertex.first], texturePositions[vertex.second]!!) + val input = Vec4(drawPositions[vertex.first], 1.0f) + val output = modelMatrix * input + mesh.addVertex( + position = output.toVec3(), + textureCoordinates = texturePositions[vertex.second]!!, + texture = texture, + tintColor = if (face.tint) { + tintColor + } else { + null + } + ) } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDFontMesh.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDFontMesh.kt index 3ad74f51d..5fb2a936a 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDFontMesh.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDFontMesh.kt @@ -13,46 +13,67 @@ package de.bixilon.minosoft.gui.rendering.hud.elements.text +import de.bixilon.minosoft.data.text.RGBColor import glm_.BYTES +import glm_.vec2.Vec2 +import glm_.vec3.Vec3 import org.lwjgl.opengl.GL11.GL_FLOAT import org.lwjgl.opengl.GL20.glEnableVertexAttribArray import org.lwjgl.opengl.GL20.glVertexAttribPointer import org.lwjgl.opengl.GL30.* -class HUDFontMesh(data: FloatArray) { - var vAO: Int = glGenVertexArrays() - var vBO: Int = glGenBuffers() - var trianglesCount: Int = data.size / FLOAT_PER_VERTEX +class HUDFontMesh { + private val data: MutableList = mutableListOf() + private var vao: Int = 0 + private var vbo: Int = 0 + private var trianglesCount: Int = 0 + + + fun load() { + trianglesCount = data.size / FLOATS_PER_VERTEX + vao = glGenVertexArrays() + vbo = glGenBuffers() + + // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s). + glBindVertexArray(vao) + glBindBuffer(GL_ARRAY_BUFFER, vbo) + glBufferData(GL_ARRAY_BUFFER, data.toFloatArray(), GL_STATIC_DRAW) + var index = 0 + glVertexAttribPointer(index, 3, GL_FLOAT, false, FLOATS_PER_VERTEX * Float.BYTES, 0L) + glEnableVertexAttribArray(index++) + glVertexAttribPointer(index, 2, GL_FLOAT, false, FLOATS_PER_VERTEX * Float.BYTES, (3 * Float.BYTES).toLong()) + glEnableVertexAttribArray(index++) + glVertexAttribPointer(index, 1, GL_FLOAT, false, FLOATS_PER_VERTEX * Float.BYTES, (5 * Float.BYTES).toLong()) + glEnableVertexAttribArray(index++) + glVertexAttribPointer(index, 1, GL_FLOAT, false, FLOATS_PER_VERTEX * Float.BYTES, (6 * Float.BYTES).toLong()) + glEnableVertexAttribArray(index++) + + // note that this is allowed, the call to glVertexAttribPointer registered vbo as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind + glBindBuffer(GL_ARRAY_BUFFER, 0) + } + + + fun addVertex(position: Vec3, textureCoordinates: Vec2, atlasPage: Int, color: RGBColor) { + data.add(position.x) + data.add(position.y) + data.add(position.z) + data.add(textureCoordinates.x) + data.add(textureCoordinates.y) + data.add(Float.fromBits(atlasPage)) + data.add(Float.fromBits(color.color)) + } fun draw() { - glBindVertexArray(vAO) + glBindVertexArray(vao) glDrawArrays(GL_TRIANGLES, 0, trianglesCount) } fun unload() { - glDeleteVertexArrays(vAO) - glDeleteBuffers(vBO) - } - - init { - // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s). - glBindVertexArray(vAO) - glBindBuffer(GL_ARRAY_BUFFER, vBO) - glBufferData(GL_ARRAY_BUFFER, data, GL_STATIC_DRAW) - glVertexAttribPointer(0, 3, GL_FLOAT, false, FLOAT_PER_VERTEX * Float.BYTES, 0L) - glEnableVertexAttribArray(0) - glVertexAttribPointer(1, 2, GL_FLOAT, false, FLOAT_PER_VERTEX * Float.BYTES, (3 * Float.BYTES).toLong()) - glEnableVertexAttribArray(1) - glVertexAttribPointer(2, 1, GL_FLOAT, false, FLOAT_PER_VERTEX * Float.BYTES, (5 * Float.BYTES).toLong()) - glEnableVertexAttribArray(2) - glVertexAttribPointer(3, 1, GL_FLOAT, false, FLOAT_PER_VERTEX * Float.BYTES, (6 * Float.BYTES).toLong()) - glEnableVertexAttribArray(3) - - // note that this is allowed, the call to glVertexAttribPointer registered VBO as the vertex attribute's bound vertex buffer object so afterwards we can safely unbind - glBindBuffer(GL_ARRAY_BUFFER, 0) + glDeleteVertexArrays(vao) + glDeleteBuffers(vbo) } companion object { - private const val FLOAT_PER_VERTEX = 7 + private const val FLOATS_PER_VERTEX = 7 } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDTextElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDTextElement.kt index 346968b27..9ec0df670 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDTextElement.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/text/HUDTextElement.kt @@ -27,6 +27,7 @@ import de.bixilon.minosoft.protocol.network.Connection import glm_.glm import glm_.mat4x4.Mat4 import glm_.vec2.Vec2 +import glm_.vec3.Vec3 import glm_.vec4.Vec4 class HUDTextElement(val connection: Connection, val hudRenderer: HUDRenderer, val renderWindow: RenderWindow) : HUDElement { @@ -53,18 +54,15 @@ class HUDTextElement(val connection: Connection, val hudRenderer: HUDRenderer, v prepare() } - private fun drawTextBackground(start: Vec2, end: Vec2, perspectiveMatrix: Mat4, meshData: MutableList) { + private fun drawTextBackground(start: Vec2, end: Vec2, perspectiveMatrix: Mat4, mesh: HUDFontMesh) { fun drawLetterVertex(position: Vec2) { val matrixPosition = perspectiveMatrix * Vec4(position.x, position.y, 0f, 1f) - meshData.add(matrixPosition.x) - meshData.add(matrixPosition.y) - meshData.add(-0.995f) - - meshData.add(0f) - meshData.add(0f) - meshData.add(Float.fromBits(0)) - - meshData.add(Float.fromBits(RGBColor(0, 0, 0, 76).color)) + mesh.addVertex( + position = Vec3(matrixPosition.x, matrixPosition.y, TEXT_BACKGROUND_Z), + textureCoordinates = TEXT_BACKGROUND_ATLAS_COORDINATES, + atlasPage = TEXT_BACKGROUND_ATLAS_INDEX, + color = TEXT_BACKGROUND_COLOR, + ) } drawLetterVertex(start) @@ -76,14 +74,14 @@ class HUDTextElement(val connection: Connection, val hudRenderer: HUDRenderer, v } - fun drawChatComponent(position: Vec2, binding: FontBindings, text: ChatComponent, meshData: MutableList, maxSize: Vec2) { + fun drawChatComponent(position: Vec2, binding: FontBindings, text: ChatComponent, mesh: HUDFontMesh, maxSize: Vec2) { if (text.message.isBlank()) { maxSize += Vec2(0, font.charHeight * hudRenderer.hudScale.scale) return } - text.addVerticies(position, Vec2(0), fontBindingPerspectiveMatrices[binding.ordinal], binding, font, hudRenderer.hudScale, meshData, maxSize) + text.addVerticies(position, Vec2(0), fontBindingPerspectiveMatrices[binding.ordinal], binding, font, hudRenderer.hudScale, mesh, maxSize) - drawTextBackground(position - 1, (position + maxSize) + 1, fontBindingPerspectiveMatrices[binding.ordinal], meshData) + drawTextBackground(position - 1, (position + maxSize) + 1, fontBindingPerspectiveMatrices[binding.ordinal], mesh) } override fun prepare() { @@ -105,7 +103,7 @@ class HUDTextElement(val connection: Connection, val hudRenderer: HUDRenderer, v hudTextElement.update() } - val meshData: MutableList = mutableListOf() + val mesh = HUDFontMesh() for ((binding, components) in componentsBindingMap) { val offset = Vec2(3, 3) @@ -116,12 +114,13 @@ class HUDTextElement(val connection: Connection, val hudRenderer: HUDRenderer, v for ((_, component) in components.withIndex()) { val currentOffset = Vec2() - drawChatComponent(offset, binding, ChatComponent.valueOf(component), meshData, currentOffset) + drawChatComponent(offset, binding, ChatComponent.valueOf(component), mesh, currentOffset) offset += Vec2(0, currentOffset.y + 1) } } + mesh.load() hudMeshHUD.unload() - hudMeshHUD = HUDFontMesh(meshData.toFloatArray()) + hudMeshHUD = mesh } @@ -131,7 +130,8 @@ class HUDTextElement(val connection: Connection, val hudRenderer: HUDRenderer, v fontAtlasTexture = font.createAtlasTexture() fontAtlasTexture.load() - hudMeshHUD = HUDFontMesh(floatArrayOf()) + hudMeshHUD = HUDFontMesh() + hudMeshHUD.load() fontShader = Shader("font_vertex.glsl", "font_fragment.glsl") fontShader.load() @@ -157,4 +157,13 @@ class HUDTextElement(val connection: Connection, val hudRenderer: HUDRenderer, v } hudMeshHUD.draw() } + + companion object { + + private const val TEXT_BACKGROUND_Z = -0.995f + private val TEXT_BACKGROUND_ATLAS_COORDINATES = Vec2() + private val TEXT_BACKGROUND_ATLAS_INDEX = 0 + private val TEXT_BACKGROUND_COLOR = RGBColor(0, 0, 0, 80) + + } } diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketJoinGame.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketJoinGame.kt index a5e427b48..b263d1226 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketJoinGame.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/clientbound/play/PacketJoinGame.kt @@ -61,7 +61,7 @@ class PacketJoinGame : ClientboundPacket() { } if (buffer.versionId < ProtocolVersions.V_1_9_1) { - dimension = buffer.connection.mapping.dimensionRegistry.get(buffer.readByte().toInt())!! + dimension = buffer.connection.mapping.dimensionRegistry.get(buffer.readByte().toInt()) difficulty = Difficulties.byId(buffer.readUnsignedByte().toInt()) maxPlayers = buffer.readByte().toInt() if (buffer.versionId >= ProtocolVersions.V_13W42B) { @@ -80,7 +80,7 @@ class PacketJoinGame : ClientboundPacket() { buffer.readStringArray() // world } if (buffer.versionId < ProtocolVersions.V_20W21A) { - dimension = buffer.connection.mapping.dimensionRegistry.get(buffer.readInt())!! + dimension = buffer.connection.mapping.dimensionRegistry.get(buffer.readInt()) } else { val dimensionCodec = buffer.readNBT() dimensions = parseDimensionCodec(dimensionCodec, buffer.versionId)