diff --git a/pom.xml b/pom.xml index 3fe497af4..bba9551fa 100644 --- a/pom.xml +++ b/pom.xml @@ -346,10 +346,5 @@ moshi-kotlin 1.11.0 - - commons-primitives - commons-primitives - 1.0 - 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 12adb593e..66bbc2d97 100644 --- a/src/main/java/de/bixilon/minosoft/data/text/TextComponent.kt +++ b/src/main/java/de/bixilon/minosoft/data/text/TextComponent.kt @@ -215,10 +215,11 @@ open class TextComponent : ChatComponent { // add all chars for (char in charArray) { if (char == '\n') { - val yOffset = offset.y - offset *= 0 - offset += Vec2(0, yOffset + Font.CHAR_HEIGHT + RenderConstants.TEXT_LINE_PADDING) - retMaxSize += Vec2(0, yOffset + Font.CHAR_HEIGHT + RenderConstants.TEXT_LINE_PADDING) + offset.x = 0 + offset.y = 0 + val yOffset = offset.y + Font.CHAR_HEIGHT + RenderConstants.TEXT_LINE_PADDING + offset.y += yOffset + retMaxSize.y += yOffset continue } val fontChar = font.getChar(char) @@ -228,7 +229,7 @@ open class TextComponent : ChatComponent { textElement.addChild(ImageElement(charStart, fontChar, charStart + Vec2(scaledWidth, Font.CHAR_HEIGHT), z, color)) // ad spacer between chars - offset += Vec2i(scaledWidth + Font.SPACE_BETWEEN_CHARS, 0f) + offset.x += scaledWidth + Font.SPACE_BETWEEN_CHARS if (offset.x > retMaxSize.x) { retMaxSize.x += scaledWidth + Font.SPACE_BETWEEN_CHARS } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderConstants.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderConstants.kt index 75ed9ed85..59717c5ec 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderConstants.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderConstants.kt @@ -46,6 +46,7 @@ object RenderConstants { const val CHUNK_SECTIONS_PER_MESH = 1 const val FRUSTUM_CULLING_ENABLED = true + const val SHOW_FPS_IN_WINDOW_TITLE = true const val MAXIMUM_CALLS_PER_FRAME = 10 } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt index 70b260cba..55a8ded25 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderWindow.kt @@ -383,7 +383,9 @@ class RenderWindow( } renderStats.endFrame() - glfwSetWindowTitle(windowId, "FPS: ${renderStats.fpsLastSecond}") + if (RenderConstants.SHOW_FPS_IN_WINDOW_TITLE) { + glfwSetWindowTitle(windowId, "Minosoft | FPS: ${renderStats.fpsLastSecond}") + } } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/SectionArrayMesh.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/SectionArrayMesh.kt index 50e61180c..0f0772f1d 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/SectionArrayMesh.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/SectionArrayMesh.kt @@ -24,20 +24,12 @@ import org.lwjgl.opengl.GL11.GL_FLOAT import org.lwjgl.opengl.GL20.glEnableVertexAttribArray import org.lwjgl.opengl.GL20.glVertexAttribPointer -class SectionArrayMesh : Mesh() { +class SectionArrayMesh : Mesh(initialCacheSize = 100000) { var lowestBlockHeight = 0 var highestBlockHeight = 0 fun addVertex(position: Vec3, textureCoordinates: Vec2, texture: Texture, tintColor: RGBColor?, lightLevel: Int = 14) { val data = data!! - data.add(position.x) - data.add(position.y) - data.add(position.z) - data.add(textureCoordinates.x * texture.uvEnd.x) - data.add(textureCoordinates.y * texture.uvEnd.y) - data.add(Float.fromBits((texture.arrayId shl 24) or texture.arrayLayer)) - - data.add(Float.fromBits(texture.properties.animation?.animationId ?: -1)) val color = tintColor ?: ChatColors.WHITE @@ -45,8 +37,17 @@ class SectionArrayMesh : Mesh() { val lightColor = RGBColor(color.red / lightFactor, color.green / lightFactor, color.blue / lightFactor) - - data.add(Float.fromBits(lightColor.color ushr 8)) + data.addAll(floatArrayOf( + position.x, + position.y, + position.z, + textureCoordinates.x * texture.uvEnd.x, + textureCoordinates.y * texture.uvEnd.y, + Float.fromBits((texture.arrayId shl 24) or texture.arrayLayer), + Float.fromBits(texture.properties.animation?.animationId ?: -1), + Float.fromBits(lightColor.color ushr 8), + ) + ) } override fun load() { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/HUDCacheMesh.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/HUDCacheMesh.kt index 07dda79ce..48457ed4e 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/HUDCacheMesh.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/HUDCacheMesh.kt @@ -15,33 +15,37 @@ package de.bixilon.minosoft.gui.rendering.hud import de.bixilon.minosoft.data.text.RGBColor import de.bixilon.minosoft.gui.rendering.textures.Texture +import de.bixilon.minosoft.util.collections.ArrayFloatList import glm_.vec2.Vec2 import glm_.vec3.Vec3 -import org.apache.commons.collections.primitives.ArrayFloatList -class HUDCacheMesh { - private val data = ArrayFloatList() +class HUDCacheMesh( + initialCacheSize: Int = 1000, +) { + private val data = ArrayFloatList(initialCacheSize) val cache: ArrayFloatList get() = data fun addVertex(position: Vec3, textureCoordinates: Vec2, texture: Texture?, tintColor: RGBColor? = null) { - data.add(position.x) - data.add(position.y) - data.add(position.z) - data.add(textureCoordinates.x) - data.add(textureCoordinates.y) - data.add(Float.fromBits((texture?.arrayLayer ?: 0) or ((texture?.arrayId ?: 0) shl 24))) + data.addAll(floatArrayOf( + position.x, + position.y, + position.z, + textureCoordinates.x, + textureCoordinates.y, + Float.fromBits((texture?.arrayLayer ?: 0) or ((texture?.arrayId ?: 0) shl 24)), + if (tintColor == null) { + 0f + } else { + Float.fromBits(tintColor.color) + }, + )) - if (tintColor == null) { - data.add(0f) - } else { - data.add(Float.fromBits(tintColor.color)) - } } val size: Int - get() = data.size() + get() = data.size fun isEmpty(): Boolean { return data.isEmpty diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/Element.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/Element.kt index 43f0e3648..f2b858708 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/Element.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/Element.kt @@ -19,6 +19,7 @@ import glm_.vec2.Vec2i abstract class Element( private var _start: Vec2i, + initialCacheSize: Int = 1000, ) { var start: Vec2i get() { @@ -30,7 +31,7 @@ abstract class Element( clearCache() } - val cache = HUDCacheMesh() + val cache = HUDCacheMesh(initialCacheSize) open var parent: Element? = null var size: Vec2i = Vec2i() diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/EndElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/EndElement.kt index aa2856d04..e39947b43 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/EndElement.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/EndElement.kt @@ -18,7 +18,8 @@ import glm_.vec2.Vec2i abstract class EndElement( start: Vec2i, private var _end: Vec2i, -) : Element(start) { + initialCacheSize: Int = 10000, +) : Element(start, initialCacheSize = initialCacheSize) { var end: Vec2i get() { return _end diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/HealthBar.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/HealthBar.kt index b278bb887..30a4b3818 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/HealthBar.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/HealthBar.kt @@ -36,7 +36,7 @@ class HealthBar( private val singleHeartSize = blackHeartContainerAtlasElement.binding.size private val width = singleHeartSize.x * MAX_HEARTS_IN_ROW - private val alternativeText = TextElement(font = font, start = Vec2i(), background = false) + private val alternativeText = TextElement(font = font, start = Vec2i(0, 0), background = false) private var _value = 0.0f var value: Float get() = _value diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/ImageElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/ImageElement.kt index 95e4e4c45..3e47fff1c 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/ImageElement.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/ImageElement.kt @@ -28,7 +28,8 @@ class ImageElement( end: Vec2i = textureLike?.size ?: Vec2i(0, 0), val z: Int = 0, val tintColor: RGBColor? = null, -) : EndElement(start, end) { +) : EndElement(start, end, initialCacheSize = 42) { + init { recalculateSize() } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/TextElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/TextElement.kt index 3edb7160c..1cccd40d7 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/TextElement.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/hud/elements/primitive/TextElement.kt @@ -49,7 +49,7 @@ class TextElement( size = if (text.message.isBlank()) { Vec2i(0, Font.CHAR_HEIGHT) } else { - val textSize = Vec2i() + val textSize = Vec2i(0, 0) text.prepareRender(Vec2i(0, 1), Vec2i(), font, this, this.z + z + 1, textSize) if (background) { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/util/Mesh.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/util/Mesh.kt index ad9ae5c93..a09d35f39 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/util/Mesh.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/util/Mesh.kt @@ -13,13 +13,15 @@ package de.bixilon.minosoft.gui.rendering.util -import org.apache.commons.collections.primitives.ArrayFloatList +import de.bixilon.minosoft.util.collections.ArrayFloatList import org.lwjgl.opengl.GL11.GL_TRIANGLES import org.lwjgl.opengl.GL11.glDrawArrays import org.lwjgl.opengl.GL30.* -abstract class Mesh { - protected var data: ArrayFloatList? = ArrayFloatList() +abstract class Mesh( + initialCacheSize: Int = 10000, +) { + protected var data: ArrayFloatList? = ArrayFloatList(initialCacheSize) private var vao: Int = -1 private var vbo: Int = -1 var trianglesCount: Int = -1 @@ -34,7 +36,7 @@ abstract class Mesh { protected fun initializeBuffers(floatsPerVertex: Int) { check(state == MeshStates.PREPARING) { "Mesh already loaded: $state" } - trianglesCount = data!!.size() / floatsPerVertex + trianglesCount = data!!.size / floatsPerVertex vao = glGenVertexArrays() vbo = glGenBuffers() glBindVertexArray(vao) diff --git a/src/main/java/de/bixilon/minosoft/util/collections/ArrayFloatList.kt b/src/main/java/de/bixilon/minosoft/util/collections/ArrayFloatList.kt new file mode 100644 index 000000000..4750cd5d6 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/util/collections/ArrayFloatList.kt @@ -0,0 +1,82 @@ +/* + * Minosoft + * Copyright (C) 2021 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.util.collections + +class ArrayFloatList( + private val initialSize: Int = 1000, +) { + private var data: FloatArray = FloatArray(initialSize) + val limit: Int + get() = data.size + var size = 0 + private set + val isEmpty: Boolean + get() = size == 0 + + private var output: FloatArray = FloatArray(0) + private var outputUpToDate = false + + fun clear() { + size = 0 + data = FloatArray(initialSize) + outputUpToDate = false + output = FloatArray(0) + } + + private fun ensureSize(needed: Int) { + if (limit - size >= needed) { + return + } + var newSize = data.size + while (newSize - size < needed) { + newSize += initialSize + } + val oldData = data + data = FloatArray(newSize) + System.arraycopy(oldData, 0, data, 0, oldData.size) + } + + fun add(float: Float) { + ensureSize(1) + data[size++] = float + outputUpToDate = false + } + + fun addAll(floats: FloatArray) { + ensureSize(floats.size) + System.arraycopy(floats, 0, data, size, floats.size) + size += floats.size + outputUpToDate = false + } + + fun addAll(floats: ArrayFloatList) { + ensureSize(floats.size) + System.arraycopy(floats.data, 0, data, size, floats.size) + size += floats.size + } + + private fun checkOutputArray() { + if (outputUpToDate) { + return + } + output = FloatArray(size) + System.arraycopy(data, 0, output, 0, size) + outputUpToDate = true + } + + fun toArray(): FloatArray { + checkOutputArray() + return output + } +}