registry: make byId not return nullable value, improve meshes

This commit is contained in:
Bixilon 2021-02-25 19:22:46 +01:00
parent ce4acbe725
commit 4fc8e425ce
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
13 changed files with 172 additions and 118 deletions

View File

@ -31,8 +31,8 @@ open class Registry<T : RegistryItem>(
return resourceLocationMap[resourceLocation] ?: parentRegistry?.get(resourceLocation) return resourceLocationMap[resourceLocation] ?: parentRegistry?.get(resourceLocation)
} }
open fun get(id: Int): T? { open fun get(id: Int): T {
return idMap[id] ?: parentRegistry?.get(id) return idMap[id] ?: parentRegistry?.get(id)!!
} }
open fun getId(value: T): Int { open fun getId(value: T): Int {

View File

@ -34,7 +34,7 @@ data class Block(
val states: MutableSet<BlockState> = mutableSetOf() val states: MutableSet<BlockState> = mutableSetOf()
override fun postInit(versionMapping: VersionMapping) { override fun postInit(versionMapping: VersionMapping) {
item = versionMapping.itemRegistry.get(itemId)!! item = versionMapping.itemRegistry.get(itemId)
} }
companion object : ResourceLocationDeserializer<Block> { companion object : ResourceLocationDeserializer<Block> {

View File

@ -26,7 +26,7 @@ class ItemRegistry(
) : Registry<Item>(parentRegistry = parentRegistry, initialSize = initialSize) { ) : Registry<Item>(parentRegistry = parentRegistry, initialSize = initialSize) {
private var flattened = false private var flattened = false
override fun get(id: Int): Item? { override fun get(id: Int): Item {
return if (!flattened) { return if (!flattened) {
val itemId = id ushr 16 val itemId = id ushr 16
val itemMeta = id and 0xFFFF val itemMeta = id and 0xFFFF
@ -35,7 +35,11 @@ class ItemRegistry(
if (itemMeta > 0 && itemMeta < Short.MAX_VALUE) { if (itemMeta > 0 && itemMeta < Short.MAX_VALUE) {
versionItemId = versionItemId or itemMeta 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 { } else {
super.get(id) super.get(id)
} }

View File

@ -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.Font;
import de.bixilon.minosoft.gui.rendering.font.FontBindings; import de.bixilon.minosoft.gui.rendering.font.FontBindings;
import de.bixilon.minosoft.gui.rendering.hud.HUDScale; 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.modding.event.events.annotations.Unsafe;
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition; import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition;
import de.bixilon.minosoft.util.hash.BetterHashSet; import de.bixilon.minosoft.util.hash.BetterHashSet;
@ -33,7 +34,6 @@ import javax.annotation.Nullable;
import java.text.CharacterIterator; import java.text.CharacterIterator;
import java.text.StringCharacterIterator; import java.text.StringCharacterIterator;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
public class BaseComponent extends ChatComponent { public class BaseComponent extends ChatComponent {
private static final String LEGACY_RESET_SUFFIX = String.valueOf(ProtocolDefinition.TEXT_COMPONENT_SPECIAL_PREFIX_CHAR) + PostChatFormattingCodes.RESET.getChar(); 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 @Override
public void addVerticies(Vec2 startPosition, Vec2 offset, Mat4 perspectiveMatrix, FontBindings binding, Font font, HUDScale hudScale, List<Float> 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) { if (binding == FontBindings.RIGHT_DOWN || binding == FontBindings.RIGHT_UP) {
for (int i = this.parts.size() - 1; i >= 0; i--) { 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 { } else {
for (var chatPart : this.parts) { 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);
} }
} }
} }

View File

@ -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.Font;
import de.bixilon.minosoft.gui.rendering.font.FontBindings; import de.bixilon.minosoft.gui.rendering.font.FontBindings;
import de.bixilon.minosoft.gui.rendering.hud.HUDScale; import de.bixilon.minosoft.gui.rendering.hud.HUDScale;
import de.bixilon.minosoft.gui.rendering.hud.elements.text.HUDFontMesh;
import glm_.mat4x4.Mat4; import glm_.mat4x4.Mat4;
import glm_.vec2.Vec2; import glm_.vec2.Vec2;
import javafx.collections.FXCollections; import javafx.collections.FXCollections;
@ -28,7 +29,6 @@ import javafx.collections.ObservableList;
import javafx.scene.Node; import javafx.scene.Node;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.util.List;
public abstract class ChatComponent { public abstract class ChatComponent {
public static ChatComponent valueOf(Object raw) { public static ChatComponent valueOf(Object raw) {
@ -96,5 +96,5 @@ public abstract class ChatComponent {
/** /**
* @return Adds all verticies to the array (used in opengl) * @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<Float> meshData, Vec2 maxSize); public abstract void addVerticies(Vec2 startPosition, Vec2 offset, Mat4 perspectiveMatrix, FontBindings binding, Font font, HUDScale hudScale, HUDFontMesh mesh, Vec2 maxSize);
} }

View File

@ -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.FontBindings
import de.bixilon.minosoft.gui.rendering.font.FontChar import de.bixilon.minosoft.gui.rendering.font.FontChar
import de.bixilon.minosoft.gui.rendering.hud.HUDScale 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.protocol.protocol.ProtocolDefinition
import de.bixilon.minosoft.util.Util import de.bixilon.minosoft.util.Util
import de.bixilon.minosoft.util.hash.BetterHashSet import de.bixilon.minosoft.util.hash.BetterHashSet
import glm_.mat4x4.Mat4 import glm_.mat4x4.Mat4
import glm_.vec2.Vec2 import glm_.vec2.Vec2
import glm_.vec3.Vec3
import glm_.vec4.Vec4 import glm_.vec4.Vec4
import javafx.animation.Animation import javafx.animation.Animation
import javafx.animation.KeyFrame import javafx.animation.KeyFrame
@ -201,25 +203,20 @@ open class TextComponent : ChatComponent {
return nodes return nodes
} }
override fun addVerticies(startPosition: Vec2, offset: Vec2, perspectiveMatrix: Mat4, binding: FontBindings, font: Font, hudScale: HUDScale, meshData: MutableList<Float>, maxSize: Vec2) { override fun addVerticies(startPosition: Vec2, offset: Vec2, perspectiveMatrix: Mat4, binding: FontBindings, font: Font, hudScale: HUDScale, mesh: HUDFontMesh, maxSize: Vec2) {
fun drawLetterVertex(position: Vec2, uv: Vec2, atlasPage: Int, color: RGBColor, meshData: MutableList<Float>) {
fun drawLetterVertex(position: Vec3, uv: Vec2, atlasPage: Int) {
val matrixPosition = perspectiveMatrix * Vec4(position.x, position.y, 0f, 1f) val matrixPosition = perspectiveMatrix * Vec4(position.x, position.y, 0f, 1f)
meshData.add(matrixPosition.x) mesh.addVertex(Vec3(matrixPosition.x, matrixPosition.y, position.z), uv, atlasPage, color)
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))
} }
fun drawLetter(position: Vec2, scaledWidth: Float, scaledHeight: Float, fontChar: FontChar, color: RGBColor, meshData: MutableList<Float>) { fun drawLetter(position: Vec2, scaledWidth: Float, scaledHeight: Float, fontChar: FontChar) {
drawLetterVertex(Vec2(position.x, position.y), fontChar.texturePosition[texturePositionCoordinates[binding.ordinal][0]], fontChar.atlasTextureIndex, color, meshData) drawLetterVertex(Vec3(position.x, position.y, HUD_Z_COORDINATE), fontChar.texturePosition[texturePositionCoordinates[binding.ordinal][0]], fontChar.atlasTextureIndex)
drawLetterVertex(Vec2(position.x, position.y + scaledHeight), fontChar.texturePosition[texturePositionCoordinates[binding.ordinal][3]], fontChar.atlasTextureIndex, color, meshData) drawLetterVertex(Vec3(position.x, position.y + scaledHeight, HUD_Z_COORDINATE), fontChar.texturePosition[texturePositionCoordinates[binding.ordinal][3]], fontChar.atlasTextureIndex)
drawLetterVertex(Vec2(position.x + scaledWidth, position.y), fontChar.texturePosition[texturePositionCoordinates[binding.ordinal][1]], fontChar.atlasTextureIndex, color, meshData) drawLetterVertex(Vec3(position.x + scaledWidth, position.y, HUD_Z_COORDINATE), fontChar.texturePosition[texturePositionCoordinates[binding.ordinal][1]], fontChar.atlasTextureIndex)
drawLetterVertex(Vec2(position.x + scaledWidth, position.y), fontChar.texturePosition[texturePositionCoordinates[binding.ordinal][1]], fontChar.atlasTextureIndex, color, meshData) drawLetterVertex(Vec3(position.x + scaledWidth, position.y, HUD_Z_COORDINATE), fontChar.texturePosition[texturePositionCoordinates[binding.ordinal][1]], fontChar.atlasTextureIndex)
drawLetterVertex(Vec2(position.x, position.y + scaledHeight), fontChar.texturePosition[texturePositionCoordinates[binding.ordinal][3]], fontChar.atlasTextureIndex, color, meshData) drawLetterVertex(Vec3(position.x, position.y + scaledHeight, HUD_Z_COORDINATE), fontChar.texturePosition[texturePositionCoordinates[binding.ordinal][3]], fontChar.atlasTextureIndex)
drawLetterVertex(Vec2(position.x + scaledWidth, position.y + scaledHeight), fontChar.texturePosition[texturePositionCoordinates[binding.ordinal][2]], fontChar.atlasTextureIndex, color, meshData) drawLetterVertex(Vec3(position.x + scaledWidth, position.y + scaledHeight, HUD_Z_COORDINATE), fontChar.texturePosition[texturePositionCoordinates[binding.ordinal][2]], fontChar.atlasTextureIndex)
} }
// reverse text if right bound // reverse text if right bound
val charArray = when (binding) { val charArray = when (binding) {
@ -260,7 +257,7 @@ open class TextComponent : ChatComponent {
} }
val fontChar = font.getChar(char) val fontChar = font.getChar(char)
val scaledX = fontChar.width * (font.charHeight / fontChar.height.toFloat()) * hudScale.scale 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) offset += Vec2(scaledX + (hudScale.scale / 2), 0f)
if (offset.x >= maxSize.x) { if (offset.x >= maxSize.x) {
maxSize.x += scaledX + (hudScale.scale / 2) maxSize.x += scaledX + (hudScale.scale / 2)
@ -280,5 +277,7 @@ open class TextComponent : ChatComponent {
listOf(2, 3, 0, 1), listOf(2, 3, 0, 1),
listOf(3, 2, 1, 0), listOf(3, 2, 1, 0),
) // matches FontBindings::ordinal ) // matches FontBindings::ordinal
const val HUD_Z_COORDINATE = -0.997f
} }
} }

View File

@ -13,22 +13,51 @@
package de.bixilon.minosoft.gui.rendering.chunk 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_.BYTES
import glm_.vec2.Vec2
import glm_.vec3.Vec3
import org.lwjgl.opengl.GL11.GL_FLOAT import org.lwjgl.opengl.GL11.GL_FLOAT
import org.lwjgl.opengl.GL20.glEnableVertexAttribArray import org.lwjgl.opengl.GL20.glEnableVertexAttribArray
import org.lwjgl.opengl.GL20.glVertexAttribPointer import org.lwjgl.opengl.GL20.glVertexAttribPointer
import org.lwjgl.opengl.GL30.* import org.lwjgl.opengl.GL30.*
class WorldMesh(data: FloatArray) { class ChunkMesh {
var vAO: Int = glGenVertexArrays() private val data: MutableList<Float> = mutableListOf()
var vBO: Int = glGenBuffers() private var vao: Int = 0
var trianglesCount: Int = data.size / FLOATS_PER_VERTEX 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). // bind the Vertex Array Object first, then bind and set vertex buffer(s), and then configure vertex attributes(s).
glBindVertexArray(vAO) glBindVertexArray(vao)
glBindBuffer(GL_ARRAY_BUFFER, vBO) glBindBuffer(GL_ARRAY_BUFFER, vbo)
glBufferData(GL_ARRAY_BUFFER, data, GL_STATIC_DRAW) glBufferData(GL_ARRAY_BUFFER, data.toFloatArray(), GL_STATIC_DRAW)
var index = 0 var index = 0
glVertexAttribPointer(index, 3, GL_FLOAT, false, FLOATS_PER_VERTEX * Float.BYTES, 0L) glVertexAttribPointer(index, 3, GL_FLOAT, false, FLOATS_PER_VERTEX * Float.BYTES, 0L)
glEnableVertexAttribArray(index++) glEnableVertexAttribArray(index++)
@ -53,13 +82,13 @@ class WorldMesh(data: FloatArray) {
} }
fun draw() { fun draw() {
glBindVertexArray(vAO) glBindVertexArray(vao)
glDrawArrays(GL_TRIANGLES, 0, trianglesCount) glDrawArrays(GL_TRIANGLES, 0, trianglesCount)
} }
fun unload() { fun unload() {
glDeleteVertexArrays(vAO) glDeleteVertexArrays(vao)
glDeleteBuffers(vBO) glDeleteBuffers(vbo)
} }
companion object { companion object {

View File

@ -36,12 +36,12 @@ import java.util.concurrent.ConcurrentHashMap
class ChunkRenderer(private val connection: Connection, private val world: World, val renderWindow: RenderWindow) : Renderer { class ChunkRenderer(private val connection: Connection, private val world: World, val renderWindow: RenderWindow) : Renderer {
private lateinit var minecraftTextures: TextureArray private lateinit var minecraftTextures: TextureArray
lateinit var chunkShader: Shader lateinit var chunkShader: Shader
private val chunkSectionsToDraw = ConcurrentHashMap<ChunkLocation, ConcurrentHashMap<Int, WorldMesh>>() private val chunkSectionsToDraw = ConcurrentHashMap<ChunkLocation, ConcurrentHashMap<Int, ChunkMesh>>()
private var currentTick = 0 // for animation usage private var currentTick = 0 // for animation usage
private var lastTickIncrementTime = 0L private var lastTickIncrementTime = 0L
private fun prepareChunk(chunkLocation: ChunkLocation, sectionHeight: Int, section: ChunkSection, chunk: Chunk): FloatArray { private fun prepareChunk(chunkLocation: ChunkLocation, sectionHeight: Int, section: ChunkSection, chunk: Chunk): ChunkMesh {
val data: MutableList<Float> = mutableListOf() val mesh = ChunkMesh()
val below = world.allChunks[chunkLocation]?.sections?.get(sectionHeight - 1) val below = world.allChunks[chunkLocation]?.sections?.get(sectionHeight - 1)
val above = 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.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() { 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) { fun prepareChunkSection(chunkLocation: ChunkLocation, sectionHeight: Int, section: ChunkSection, chunk: Chunk) {
renderWindow.rendering.executor.execute { renderWindow.rendering.executor.execute {
val data = prepareChunk(chunkLocation, sectionHeight, section, chunk) val mesh = prepareChunk(chunkLocation, sectionHeight, section, chunk)
var sectionMap = chunkSectionsToDraw[chunkLocation] var sectionMap = chunkSectionsToDraw[chunkLocation]
if (sectionMap == null) { if (sectionMap == null) {
@ -178,9 +178,9 @@ class ChunkRenderer(private val connection: Connection, private val world: World
chunkSectionsToDraw[chunkLocation] = sectionMap chunkSectionsToDraw[chunkLocation] = sectionMap
} }
renderWindow.renderQueue.add { renderWindow.renderQueue.add {
val newMesh = WorldMesh(data) mesh.load()
sectionMap[sectionHeight]?.unload() sectionMap[sectionHeight]?.unload()
sectionMap[sectionHeight] = newMesh sectionMap[sectionHeight] = mesh
} }
} }
} }

View File

@ -17,6 +17,7 @@ import com.google.gson.JsonObject
import de.bixilon.minosoft.data.Directions import de.bixilon.minosoft.data.Directions
import de.bixilon.minosoft.data.text.RGBColor import de.bixilon.minosoft.data.text.RGBColor
import de.bixilon.minosoft.data.world.BlockInfo 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.chunk.models.loading.BlockModel
import de.bixilon.minosoft.gui.rendering.textures.Texture import de.bixilon.minosoft.gui.rendering.textures.Texture
import glm_.mat4x4.Mat4 import glm_.mat4x4.Mat4
@ -69,7 +70,7 @@ class BlockRenderer(data: JsonObject, parent: BlockModel) {
} }
} }
fun render(blockInfo: BlockInfo, tintColor: RGBColor?, position: Vec3, data: MutableList<Float>, neighbourBlocks: Array<BlockInfo?>) { fun render(blockInfo: BlockInfo, tintColor: RGBColor?, position: Vec3, mesh: ChunkMesh, neighbourBlocks: Array<BlockInfo?>) {
val modelMatrix = Mat4().translate(position) val modelMatrix = Mat4().translate(position)
for (direction in Directions.DIRECTIONS) { for (direction in Directions.DIRECTIONS) {
@ -90,7 +91,7 @@ class BlockRenderer(data: JsonObject, parent: BlockModel) {
continue continue
} }
element.render(tintColor, textureMapping, modelMatrix, direction, data) element.render(tintColor, textureMapping, modelMatrix, direction, mesh)
} }
} }
} }

View File

@ -17,6 +17,7 @@ import com.google.gson.JsonObject
import de.bixilon.minosoft.data.Axes import de.bixilon.minosoft.data.Axes
import de.bixilon.minosoft.data.Directions import de.bixilon.minosoft.data.Directions
import de.bixilon.minosoft.data.text.RGBColor 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.BlockModel
import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModelElement import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModelElement
import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModelFace import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModelFace
@ -28,7 +29,7 @@ import glm_.vec2.Vec2
import glm_.vec3.Vec3 import glm_.vec3.Vec3
import glm_.vec4.Vec4 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<Directions> = mutableSetOf() private val fullFaceDirections: MutableSet<Directions> = mutableSetOf()
private val faces: MutableMap<Directions, BlockModelFace> = HashMap(element.faces) private val faces: MutableMap<Directions, BlockModelFace> = HashMap(element.faces)
private var positions: Array<Vec3> = element.positions.clone() private var positions: Array<Vec3> = element.positions.clone()
@ -49,7 +50,7 @@ class ElementRenderer(element: BlockModelElement, rotation: Vec3, uvlock: Boolea
} }
fun render(tintColor: RGBColor?, textureMapping: MutableMap<String, Texture>, modelMatrix: Mat4, direction: Directions, data: MutableList<Float>) { fun render(tintColor: RGBColor?, textureMapping: MutableMap<String, Texture>, modelMatrix: Mat4, direction: Directions, mesh: ChunkMesh) {
val realDirection = directionMapping[direction]!! val realDirection = directionMapping[direction]!!
val positionTemplate = BlockModelElement.FACE_POSITION_MAP_TEMPLATE[realDirection.ordinal] 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]]) 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<Vec3>, texturePositions: Array<Vec2?>) { fun createQuad(drawPositions: Array<Vec3>, texturePositions: Array<Vec2?>) {
for (vertex in drawOrder) { 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
}
)
} }
} }

View File

@ -13,46 +13,67 @@
package de.bixilon.minosoft.gui.rendering.hud.elements.text package de.bixilon.minosoft.gui.rendering.hud.elements.text
import de.bixilon.minosoft.data.text.RGBColor
import glm_.BYTES import glm_.BYTES
import glm_.vec2.Vec2
import glm_.vec3.Vec3
import org.lwjgl.opengl.GL11.GL_FLOAT import org.lwjgl.opengl.GL11.GL_FLOAT
import org.lwjgl.opengl.GL20.glEnableVertexAttribArray import org.lwjgl.opengl.GL20.glEnableVertexAttribArray
import org.lwjgl.opengl.GL20.glVertexAttribPointer import org.lwjgl.opengl.GL20.glVertexAttribPointer
import org.lwjgl.opengl.GL30.* import org.lwjgl.opengl.GL30.*
class HUDFontMesh(data: FloatArray) { class HUDFontMesh {
var vAO: Int = glGenVertexArrays() private val data: MutableList<Float> = mutableListOf()
var vBO: Int = glGenBuffers() private var vao: Int = 0
var trianglesCount: Int = data.size / FLOAT_PER_VERTEX 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() { fun draw() {
glBindVertexArray(vAO) glBindVertexArray(vao)
glDrawArrays(GL_TRIANGLES, 0, trianglesCount) glDrawArrays(GL_TRIANGLES, 0, trianglesCount)
} }
fun unload() { fun unload() {
glDeleteVertexArrays(vAO) glDeleteVertexArrays(vao)
glDeleteBuffers(vBO) 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)
} }
companion object { companion object {
private const val FLOAT_PER_VERTEX = 7 private const val FLOATS_PER_VERTEX = 7
} }
} }

View File

@ -27,6 +27,7 @@ import de.bixilon.minosoft.protocol.network.Connection
import glm_.glm import glm_.glm
import glm_.mat4x4.Mat4 import glm_.mat4x4.Mat4
import glm_.vec2.Vec2 import glm_.vec2.Vec2
import glm_.vec3.Vec3
import glm_.vec4.Vec4 import glm_.vec4.Vec4
class HUDTextElement(val connection: Connection, val hudRenderer: HUDRenderer, val renderWindow: RenderWindow) : HUDElement { 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() prepare()
} }
private fun drawTextBackground(start: Vec2, end: Vec2, perspectiveMatrix: Mat4, meshData: MutableList<Float>) { private fun drawTextBackground(start: Vec2, end: Vec2, perspectiveMatrix: Mat4, mesh: HUDFontMesh) {
fun drawLetterVertex(position: Vec2) { fun drawLetterVertex(position: Vec2) {
val matrixPosition = perspectiveMatrix * Vec4(position.x, position.y, 0f, 1f) val matrixPosition = perspectiveMatrix * Vec4(position.x, position.y, 0f, 1f)
meshData.add(matrixPosition.x) mesh.addVertex(
meshData.add(matrixPosition.y) position = Vec3(matrixPosition.x, matrixPosition.y, TEXT_BACKGROUND_Z),
meshData.add(-0.995f) textureCoordinates = TEXT_BACKGROUND_ATLAS_COORDINATES,
atlasPage = TEXT_BACKGROUND_ATLAS_INDEX,
meshData.add(0f) color = TEXT_BACKGROUND_COLOR,
meshData.add(0f) )
meshData.add(Float.fromBits(0))
meshData.add(Float.fromBits(RGBColor(0, 0, 0, 76).color))
} }
drawLetterVertex(start) 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<Float>, maxSize: Vec2) { fun drawChatComponent(position: Vec2, binding: FontBindings, text: ChatComponent, mesh: HUDFontMesh, maxSize: Vec2) {
if (text.message.isBlank()) { if (text.message.isBlank()) {
maxSize += Vec2(0, font.charHeight * hudRenderer.hudScale.scale) maxSize += Vec2(0, font.charHeight * hudRenderer.hudScale.scale)
return 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() { override fun prepare() {
@ -105,7 +103,7 @@ class HUDTextElement(val connection: Connection, val hudRenderer: HUDRenderer, v
hudTextElement.update() hudTextElement.update()
} }
val meshData: MutableList<Float> = mutableListOf() val mesh = HUDFontMesh()
for ((binding, components) in componentsBindingMap) { for ((binding, components) in componentsBindingMap) {
val offset = Vec2(3, 3) val offset = Vec2(3, 3)
@ -116,12 +114,13 @@ class HUDTextElement(val connection: Connection, val hudRenderer: HUDRenderer, v
for ((_, component) in components.withIndex()) { for ((_, component) in components.withIndex()) {
val currentOffset = Vec2() 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) offset += Vec2(0, currentOffset.y + 1)
} }
} }
mesh.load()
hudMeshHUD.unload() 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 = font.createAtlasTexture()
fontAtlasTexture.load() fontAtlasTexture.load()
hudMeshHUD = HUDFontMesh(floatArrayOf()) hudMeshHUD = HUDFontMesh()
hudMeshHUD.load()
fontShader = Shader("font_vertex.glsl", "font_fragment.glsl") fontShader = Shader("font_vertex.glsl", "font_fragment.glsl")
fontShader.load() fontShader.load()
@ -157,4 +157,13 @@ class HUDTextElement(val connection: Connection, val hudRenderer: HUDRenderer, v
} }
hudMeshHUD.draw() 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)
}
} }

View File

@ -61,7 +61,7 @@ class PacketJoinGame : ClientboundPacket() {
} }
if (buffer.versionId < ProtocolVersions.V_1_9_1) { 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()) difficulty = Difficulties.byId(buffer.readUnsignedByte().toInt())
maxPlayers = buffer.readByte().toInt() maxPlayers = buffer.readByte().toInt()
if (buffer.versionId >= ProtocolVersions.V_13W42B) { if (buffer.versionId >= ProtocolVersions.V_13W42B) {
@ -80,7 +80,7 @@ class PacketJoinGame : ClientboundPacket() {
buffer.readStringArray() // world buffer.readStringArray() // world
} }
if (buffer.versionId < ProtocolVersions.V_20W21A) { if (buffer.versionId < ProtocolVersions.V_20W21A) {
dimension = buffer.connection.mapping.dimensionRegistry.get(buffer.readInt())!! dimension = buffer.connection.mapping.dimensionRegistry.get(buffer.readInt())
} else { } else {
val dimensionCodec = buffer.readNBT() val dimensionCodec = buffer.readNBT()
dimensions = parseDimensionCodec(dimensionCodec, buffer.versionId) dimensions = parseDimensionCodec(dimensionCodec, buffer.versionId)