mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-18 20:05:02 -04:00
rendering: code improvements
This commit is contained in:
parent
649921a468
commit
a8fcc8efe1
@ -41,15 +41,18 @@ import org.lwjgl.system.MemoryStack
|
||||
import org.lwjgl.system.MemoryUtil
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
|
||||
class RenderWindow(val connection: Connection, val rendering: Rendering) {
|
||||
class RenderWindow(
|
||||
val connection: Connection,
|
||||
val rendering: Rendering,
|
||||
) {
|
||||
private val keyBindingCallbacks: MutableMap<ResourceLocation, Pair<KeyBinding, MutableSet<((keyCode: KeyCodes, keyEvent: KeyAction) -> Unit)>>> = mutableMapOf()
|
||||
private val keysDown: MutableSet<KeyCodes> = mutableSetOf()
|
||||
private val keyBindingDown: MutableSet<KeyBinding> = mutableSetOf()
|
||||
val renderStats = RenderStats()
|
||||
var screenWidth = 900
|
||||
var screenHeight = 500
|
||||
private var windowId: Long = 0
|
||||
private var deltaTime = 0.0 // time between current frame and last frame
|
||||
private var windowId = 0L
|
||||
private var deltaFrameTime = 0.0 // time between current frame and last frame
|
||||
|
||||
private var lastFrame = 0.0
|
||||
val camera: Camera = Camera(connection, Minosoft.getConfig().config.game.camera.fov, this)
|
||||
@ -317,7 +320,7 @@ class RenderWindow(val connection: Connection, val rendering: Rendering) {
|
||||
glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT) // clear the framebuffer
|
||||
|
||||
val currentFrame = glfwGetTime()
|
||||
deltaTime = currentFrame - lastFrame
|
||||
deltaFrameTime = currentFrame - lastFrame
|
||||
lastFrame = currentFrame
|
||||
|
||||
|
||||
@ -331,7 +334,7 @@ class RenderWindow(val connection: Connection, val rendering: Rendering) {
|
||||
glfwSwapBuffers(windowId)
|
||||
glfwPollEvents()
|
||||
camera.draw()
|
||||
camera.handleInput(deltaTime)
|
||||
camera.handleInput(deltaFrameTime)
|
||||
|
||||
|
||||
// handle opengl context tasks, maximum 10 per frame
|
||||
|
@ -16,6 +16,7 @@ package de.bixilon.minosoft.gui.rendering
|
||||
import de.bixilon.minosoft.protocol.network.Connection
|
||||
import de.bixilon.minosoft.protocol.protocol.ConnectionStates
|
||||
import de.bixilon.minosoft.util.CountUpAndDownLatch
|
||||
import de.bixilon.minosoft.util.MMath
|
||||
import de.bixilon.minosoft.util.Util
|
||||
import de.bixilon.minosoft.util.logging.Log
|
||||
import org.lwjgl.Version
|
||||
@ -24,7 +25,7 @@ import java.util.concurrent.Executors
|
||||
|
||||
class Rendering(private val connection: Connection) {
|
||||
val renderWindow: RenderWindow = RenderWindow(connection, this)
|
||||
val executor: ExecutorService = Executors.newFixedThreadPool(4, Util.getThreadFactory(String.format("Rendering#%d", connection.connectionId)))
|
||||
val executor: ExecutorService = Executors.newFixedThreadPool(MMath.clamp(Runtime.getRuntime().availableProcessors() / 2, 1, 4), Util.getThreadFactory(String.format("Rendering#%d", connection.connectionId)))
|
||||
|
||||
fun start(latch: CountUpAndDownLatch) {
|
||||
latch.countUp()
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020 Moritz Zwerger, Lukas Eisenhauer
|
||||
* 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.
|
||||
*
|
||||
@ -15,19 +15,15 @@ package de.bixilon.minosoft.gui.rendering.chunk
|
||||
|
||||
import de.bixilon.minosoft.data.text.RGBColor
|
||||
import de.bixilon.minosoft.gui.rendering.textures.Texture
|
||||
import de.bixilon.minosoft.gui.rendering.util.Mesh
|
||||
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 ChunkMesh {
|
||||
private val data: MutableList<Float> = mutableListOf()
|
||||
private var vao: Int = 0
|
||||
private var vbo: Int = 0
|
||||
private var trianglesCount: Int = 0
|
||||
class ChunkMesh : Mesh() {
|
||||
|
||||
fun addVertex(position: Vec3, textureCoordinates: Vec2, texture: Texture, tintColor: RGBColor?, lightLevel: Byte = 14) {
|
||||
data.add(position.x)
|
||||
@ -51,16 +47,8 @@ class ChunkMesh {
|
||||
data.add(lightLevel / MAX_LIGHT_LEVEL)
|
||||
}
|
||||
|
||||
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)
|
||||
data.clear() // clear data ((do not store in memory)
|
||||
override fun load() {
|
||||
super.initializeBuffers(FLOATS_PER_VERTEX)
|
||||
var index = 0
|
||||
glVertexAttribPointer(index, 3, GL_FLOAT, false, FLOATS_PER_VERTEX * Float.BYTES, 0L)
|
||||
glEnableVertexAttribArray(index++)
|
||||
@ -80,22 +68,10 @@ class ChunkMesh {
|
||||
glVertexAttribPointer(index, 1, GL_FLOAT, false, FLOATS_PER_VERTEX * Float.BYTES, (10 * Float.BYTES).toLong())
|
||||
glEnableVertexAttribArray(index++)
|
||||
|
||||
// don't remove the ++ above!
|
||||
index.let { }
|
||||
|
||||
// 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)
|
||||
super.unbind()
|
||||
}
|
||||
|
||||
fun draw() {
|
||||
glBindVertexArray(vao)
|
||||
glDrawArrays(GL_TRIANGLES, 0, trianglesCount)
|
||||
}
|
||||
|
||||
fun unload() {
|
||||
glDeleteVertexArrays(vao)
|
||||
glDeleteBuffers(vbo)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val FLOATS_PER_VERTEX = 11
|
||||
|
@ -6,8 +6,8 @@ import de.bixilon.minosoft.protocol.network.Connection
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
import glm_.vec3.Vec3
|
||||
|
||||
class Frustum(val camera: Camera) {
|
||||
val normals: Array<Vec3>
|
||||
class Frustum(private val camera: Camera) {
|
||||
private val normals: Array<Vec3>
|
||||
|
||||
init {
|
||||
val realFront = Vec3(camera.cameraFront)
|
||||
@ -20,32 +20,45 @@ class Frustum(val camera: Camera) {
|
||||
camera.cameraFront.normalize(),
|
||||
// left.normalize(),
|
||||
// right.normalize(),
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private fun containsRegion(from: Vec3, to: Vec3): Boolean {
|
||||
val min = Vec3()
|
||||
for (normal in normals) {
|
||||
// get the point most likely to be in the frustum
|
||||
min.x = if (normal.x < 0) from.x else to.x
|
||||
min.y = if (normal.y < 0) from.y else to.y
|
||||
min.z = if (normal.z < 0) from.z else to.z
|
||||
min.x = if (normal.x < 0) {
|
||||
from.x
|
||||
} else {
|
||||
to.x
|
||||
}
|
||||
min.y = if (normal.y < 0) {
|
||||
from.y
|
||||
} else {
|
||||
to.y
|
||||
}
|
||||
min.z = if (normal.z < 0) {
|
||||
from.z
|
||||
} else {
|
||||
to.z
|
||||
}
|
||||
|
||||
if (dotProduct(normal, min - camera.cameraPosition) < 0f) {
|
||||
return false // region lies outside of frustum
|
||||
if (normal.dotProduct(min - camera.cameraPosition) < 0f) {
|
||||
return false // region is outside of frustum
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
private fun dotProduct(v1: Vec3, v2: Vec3): Float {
|
||||
return v1.x * v2.x + v1.y * v2.y + v1.z * v2.z
|
||||
}
|
||||
|
||||
fun containsChunk(chunkPosition: ChunkPosition, connection: Connection): Boolean {
|
||||
val from = Vec3(chunkPosition.x * ProtocolDefinition.SECTION_WIDTH_X, connection.player.world.dimension!!.minY, chunkPosition.z * ProtocolDefinition.SECTION_WIDTH_Z)
|
||||
val to = from + Vec3(ProtocolDefinition.SECTION_WIDTH_X, connection.player.world.dimension!!.logicalHeight, ProtocolDefinition.SECTION_WIDTH_Z)
|
||||
val dimension = connection.player.world.dimension!!
|
||||
val from = Vec3(chunkPosition.x * ProtocolDefinition.SECTION_WIDTH_X, dimension.minY, chunkPosition.z * ProtocolDefinition.SECTION_WIDTH_Z)
|
||||
val to = from + Vec3(ProtocolDefinition.SECTION_WIDTH_X, dimension.logicalHeight, ProtocolDefinition.SECTION_WIDTH_Z)
|
||||
val frustum = Frustum(connection.renderer.renderWindow.camera)
|
||||
return frustum.containsRegion(from, to)
|
||||
}
|
||||
}
|
||||
|
||||
private fun Vec3.dotProduct(vec3: Vec3): Float {
|
||||
return this.x * vec3.x + this.y * vec3.y + this.z * vec3.z
|
||||
}
|
||||
|
@ -32,8 +32,12 @@ import org.lwjgl.opengl.GL11.glEnable
|
||||
import org.lwjgl.opengl.GL13.glDisable
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
|
||||
class WorldRenderer(private val connection: Connection, private val world: World, val renderWindow: RenderWindow) : Renderer {
|
||||
private lateinit var minecraftTextures: TextureArray
|
||||
class WorldRenderer(
|
||||
private val connection: Connection,
|
||||
private val world: World,
|
||||
val renderWindow: RenderWindow,
|
||||
) : Renderer {
|
||||
private lateinit var blockTextureArray: TextureArray
|
||||
lateinit var chunkShader: Shader
|
||||
val chunkSectionsToDraw = ConcurrentHashMap<ChunkPosition, ConcurrentHashMap<Int, ChunkMesh>>()
|
||||
val visibleChunks: MutableSet<ChunkPosition> = mutableSetOf()
|
||||
@ -84,8 +88,8 @@ class WorldRenderer(private val connection: Connection, private val world: World
|
||||
}
|
||||
|
||||
override fun init() {
|
||||
minecraftTextures = TextureArray.createTextureArray(connection.version.assetsManager, resolveBlockTextureIds(connection.version.mapping.blockStateIdMap.values))
|
||||
minecraftTextures.load()
|
||||
blockTextureArray = TextureArray.createTextureArray(connection.version.assetsManager, resolveBlockTextureIds(connection.version.mapping.blockStateIdMap.values))
|
||||
blockTextureArray.load()
|
||||
|
||||
|
||||
chunkShader = Shader("chunk_vertex.glsl", "chunk_fragment.glsl")
|
||||
@ -94,13 +98,13 @@ class WorldRenderer(private val connection: Connection, private val world: World
|
||||
// register keybindings
|
||||
renderWindow.registerKeyCallback(KeyBindingsNames.DEBUG_CLEAR_CHUNK_CACHE) { _, _ ->
|
||||
clearChunkCache()
|
||||
connection.sender.sendFakeChatMessage("§f[§e§lDEBUG§f] §9Cleared chunk cache!")
|
||||
renderWindow.sendDebugMessage("Cleared chunk cache!")
|
||||
prepareWorld(world)
|
||||
}
|
||||
}
|
||||
|
||||
override fun postInit() {
|
||||
minecraftTextures.use(chunkShader, "blockTextureArray")
|
||||
blockTextureArray.use(chunkShader, "blockTextureArray")
|
||||
}
|
||||
|
||||
override fun draw() {
|
||||
|
@ -13,10 +13,10 @@
|
||||
|
||||
package de.bixilon.minosoft.gui.rendering.chunk.models.loading
|
||||
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonObject
|
||||
import de.bixilon.minosoft.data.Axes
|
||||
import de.bixilon.minosoft.data.Directions
|
||||
import de.bixilon.minosoft.gui.rendering.util.VecUtil
|
||||
import glm_.glm
|
||||
import glm_.vec2.Vec2
|
||||
import glm_.vec3.Vec3
|
||||
@ -26,16 +26,15 @@ open class BlockModelElement(data: JsonObject) {
|
||||
var positions: Array<Vec3>
|
||||
|
||||
init {
|
||||
var from = Vec3(0, 0, 0)
|
||||
var to = Vec3(BLOCK_RESOLUTION, BLOCK_RESOLUTION, BLOCK_RESOLUTION)
|
||||
data["from"]?.let {
|
||||
val array = it.asJsonArray
|
||||
from = Vec3(array[0].asFloat, array[1].asFloat, array[2].asFloat)
|
||||
}
|
||||
data["to"]?.let {
|
||||
val array = it.asJsonArray
|
||||
to = Vec3(array[0].asFloat, array[1].asFloat, array[2].asFloat)
|
||||
}
|
||||
val from = data["from"]?.asJsonArray?.let {
|
||||
VecUtil.jsonToVec3(it)
|
||||
} ?: Vec3()
|
||||
|
||||
val to = data["to"]?.asJsonArray?.let {
|
||||
VecUtil.jsonToVec3(it)
|
||||
} ?: Vec3(BLOCK_RESOLUTION)
|
||||
|
||||
|
||||
positions = arrayOf(
|
||||
Vec3(from),
|
||||
Vec3(to.x, from.y, from.z),
|
||||
@ -46,15 +45,15 @@ open class BlockModelElement(data: JsonObject) {
|
||||
Vec3(from.x, to.y, to.z),
|
||||
Vec3(to),
|
||||
)
|
||||
data["rotation"]?.let {
|
||||
val rotation = it.asJsonObject
|
||||
val axis = Axes.valueOf(rotation["axis"].asString.toUpperCase())
|
||||
val angle = glm.radians(rotation["angle"].asDouble)
|
||||
val rescale = rotation["rescale"]?.asBoolean ?: false
|
||||
rotatePositions(positions, axis, angle, jsonArrayToVec3(rotation["origin"].asJsonArray), rescale)
|
||||
|
||||
data["rotation"]?.asJsonObject?.let {
|
||||
val axis = Axes.valueOf(it["axis"].asString.toUpperCase())
|
||||
val angle = glm.radians(it["angle"].asDouble)
|
||||
val rescale = it["rescale"]?.asBoolean ?: false
|
||||
rotatePositions(positions, axis, angle, VecUtil.jsonToVec3(it["origin"].asJsonArray), rescale)
|
||||
}
|
||||
data["faces"]?.let {
|
||||
for ((directionName, json) in it.asJsonObject.entrySet()) {
|
||||
data["faces"]?.asJsonObject?.let {
|
||||
for ((directionName, json) in it.entrySet()) {
|
||||
val direction = Directions.valueOf(directionName.toUpperCase())
|
||||
faces[direction] = BlockModelFace(json.asJsonObject, from, to, direction)
|
||||
}
|
||||
@ -65,9 +64,7 @@ open class BlockModelElement(data: JsonObject) {
|
||||
}
|
||||
|
||||
companion object {
|
||||
fun jsonArrayToVec3(array: JsonArray): Vec3 {
|
||||
return Vec3(array[0].asFloat, array[1].asFloat, array[2].asFloat)
|
||||
}
|
||||
|
||||
const val BLOCK_RESOLUTION = 16f
|
||||
|
||||
val FACE_POSITION_MAP_TEMPLATE = arrayOf(
|
||||
@ -88,13 +85,13 @@ open class BlockModelElement(data: JsonObject) {
|
||||
private val POSITION_7 = Vec3(-0.5f, +0.5f, +0.5f) // Vec3(0, BLOCK_RESOLUTION, BLOCK_RESOLUTION)
|
||||
private val POSITION_8 = Vec3(+0.5f, +0.5f, +0.5f) // Vec3(BLOCK_RESOLUTION, BLOCK_RESOLUTION, BLOCK_RESOLUTION)
|
||||
|
||||
val fullTestPositions = mapOf(
|
||||
Directions.EAST to setOf(POSITION_1, POSITION_3, POSITION_5, POSITION_7),
|
||||
Directions.WEST to setOf(POSITION_2, POSITION_4, POSITION_6, POSITION_8),
|
||||
Directions.DOWN to setOf(POSITION_1, POSITION_2, POSITION_3, POSITION_4),
|
||||
Directions.UP to setOf(POSITION_5, POSITION_6, POSITION_7, POSITION_8),
|
||||
Directions.SOUTH to setOf(POSITION_1, POSITION_2, POSITION_5, POSITION_6),
|
||||
Directions.NORTH to setOf(POSITION_3, POSITION_4, POSITION_7, POSITION_8),
|
||||
val FULL_TEST_POSITIONS = arrayOf(
|
||||
setOf(POSITION_1, POSITION_2, POSITION_3, POSITION_4),
|
||||
setOf(POSITION_5, POSITION_6, POSITION_7, POSITION_8),
|
||||
setOf(POSITION_3, POSITION_4, POSITION_7, POSITION_8),
|
||||
setOf(POSITION_1, POSITION_2, POSITION_5, POSITION_6),
|
||||
setOf(POSITION_2, POSITION_4, POSITION_6, POSITION_8),
|
||||
setOf(POSITION_1, POSITION_3, POSITION_5, POSITION_7)
|
||||
)
|
||||
|
||||
fun getRotatedValues(x: Float, y: Float, sin: Double, cos: Double): Vec2 {
|
||||
@ -135,7 +132,7 @@ open class BlockModelElement(data: JsonObject) {
|
||||
|
||||
fun transformPosition(position: Vec3): Vec3 {
|
||||
fun positionToFloat(uv: Float): Float {
|
||||
return (uv - 8f) / BLOCK_RESOLUTION
|
||||
return (uv - (BLOCK_RESOLUTION / 2)) / BLOCK_RESOLUTION
|
||||
}
|
||||
return Vec3(positionToFloat(position.x), positionToFloat(position.y), positionToFloat(position.z))
|
||||
}
|
||||
|
@ -39,9 +39,9 @@ class ElementRenderer(element: BlockModelElement, rotation: Vec3, uvLock: Boolea
|
||||
|
||||
init {
|
||||
rotatePositionsAxes(positions, rotation, rescale)
|
||||
// TODO : uvlock
|
||||
// TODO : uvLock
|
||||
for (direction in Directions.DIRECTIONS) {
|
||||
if (positions.containsAllVectors(BlockModelElement.fullTestPositions[direction], 0.0001f)) { // TODO: check if texture is transparent ==> && ! texture.isTransparent
|
||||
if (positions.containsAllVectors(BlockModelElement.FULL_TEST_POSITIONS[direction.ordinal], 0.0001f)) { // TODO: check if texture is transparent ==> && ! texture.isTransparent
|
||||
fullFaceDirections.add(direction)
|
||||
}
|
||||
directionMapping[direction] = getRotatedDirection(rotation, direction)
|
||||
@ -68,7 +68,7 @@ class ElementRenderer(element: BlockModelElement, rotation: Vec3, uvLock: Boolea
|
||||
|
||||
|
||||
fun createQuad(drawPositions: Array<Vec3>, texturePositions: Array<Vec2?>) {
|
||||
for (vertex in drawOrder) {
|
||||
for (vertex in DRAW_ODER) {
|
||||
val input = Vec4(drawPositions[vertex.first], 1.0f)
|
||||
val output = modelMatrix * input
|
||||
mesh.addVertex(
|
||||
@ -102,25 +102,9 @@ class ElementRenderer(element: BlockModelElement, rotation: Vec3, uvLock: Boolea
|
||||
}
|
||||
|
||||
companion object {
|
||||
val EMPTY_VECTOR = Vec3()
|
||||
private val EMPTY_VECTOR = Vec3()
|
||||
|
||||
fun createElements(state: JsonObject, parent: BlockModel): MutableList<ElementRenderer> {
|
||||
val rotation = glm.radians(vec3InJsonObject(state))
|
||||
val uvLock = state["uvlock"]?.asBoolean ?: false
|
||||
val rescale = state["rescale"]?.asBoolean ?: false
|
||||
val parentElements = parent.elements
|
||||
val result: MutableList<ElementRenderer> = mutableListOf()
|
||||
for (parentElement in parentElements) {
|
||||
result.add(ElementRenderer(parentElement, rotation, true, rescale)) // uvlock is not yet implemented in the data generator
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
private fun vec3InJsonObject(json: JsonObject): Vec3 {
|
||||
return Vec3(json["x"]?.asFloat ?: 0, json["y"]?.asFloat ?: 0, json["z"]?.asFloat ?: 0)
|
||||
}
|
||||
|
||||
val drawOrder = arrayOf(
|
||||
val DRAW_ODER = arrayOf(
|
||||
Pair(0, 1),
|
||||
Pair(3, 2),
|
||||
Pair(2, 3),
|
||||
@ -129,15 +113,29 @@ class ElementRenderer(element: BlockModelElement, rotation: Vec3, uvLock: Boolea
|
||||
Pair(0, 1),
|
||||
)
|
||||
|
||||
private fun Array<Vec3>.containsAllVectors(set: Set<Vec3>?, margin: Float): Boolean {
|
||||
for (position in set!!) {
|
||||
var isIn = false
|
||||
for (testposition in this) {
|
||||
if ((position - testposition).length() < margin) {
|
||||
isIn = true
|
||||
fun createElements(state: JsonObject, parent: BlockModel): MutableList<ElementRenderer> {
|
||||
val rotation = glm.radians(state.asVec3())
|
||||
val uvLock = state["uvlock"]?.asBoolean ?: false
|
||||
val rescale = state["rescale"]?.asBoolean ?: false
|
||||
val parentElements = parent.elements
|
||||
val result: MutableList<ElementRenderer> = mutableListOf()
|
||||
for (parentElement in parentElements) {
|
||||
result.add(ElementRenderer(parentElement, rotation, uvLock, rescale))
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
private fun Array<Vec3>.containsAllVectors(their: Set<Vec3>, margin: Float): Boolean {
|
||||
for (theirPosition in their) {
|
||||
var vec3WasIn = false
|
||||
for (thisPosition in this) {
|
||||
if ((theirPosition - thisPosition).length() < margin) {
|
||||
vec3WasIn = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if (!isIn) {
|
||||
if (!vec3WasIn) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
@ -157,9 +155,13 @@ class ElementRenderer(element: BlockModelElement, rotation: Vec3, uvLock: Boolea
|
||||
if (angles == EMPTY_VECTOR) {
|
||||
return
|
||||
}
|
||||
BlockModelElement.rotatePositions(positions, Axes.X, angles.x.toDouble(), Vec3(), rescale)
|
||||
BlockModelElement.rotatePositions(positions, Axes.Y, angles.y.toDouble(), Vec3(), rescale)
|
||||
BlockModelElement.rotatePositions(positions, Axes.Z, angles.z.toDouble(), Vec3(), rescale)
|
||||
BlockModelElement.rotatePositions(positions, Axes.X, angles.x.toDouble(), EMPTY_VECTOR, rescale)
|
||||
BlockModelElement.rotatePositions(positions, Axes.Y, angles.y.toDouble(), EMPTY_VECTOR, rescale)
|
||||
BlockModelElement.rotatePositions(positions, Axes.Z, angles.z.toDouble(), EMPTY_VECTOR, rescale)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun JsonObject.asVec3(): Vec3 {
|
||||
return Vec3(this["x"]?.asFloat ?: 0, this["y"]?.asFloat ?: 0, this["z"]?.asFloat ?: 0)
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020 Moritz Zwerger
|
||||
* 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.
|
||||
*
|
||||
@ -14,31 +14,18 @@
|
||||
package de.bixilon.minosoft.gui.rendering.hud.elements.text
|
||||
|
||||
import de.bixilon.minosoft.data.text.RGBColor
|
||||
import de.bixilon.minosoft.gui.rendering.util.Mesh
|
||||
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 {
|
||||
private val data: MutableList<Float> = mutableListOf()
|
||||
private var vao: Int = 0
|
||||
private var vbo: Int = 0
|
||||
private var trianglesCount: Int = 0
|
||||
class HUDFontMesh : Mesh() {
|
||||
|
||||
|
||||
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)
|
||||
data.clear() // clear data ((do not store in memory)
|
||||
override fun load() {
|
||||
super.initializeBuffers(FLOATS_PER_VERTEX)
|
||||
var index = 0
|
||||
glVertexAttribPointer(index, 3, GL_FLOAT, false, FLOATS_PER_VERTEX * Float.BYTES, 0L)
|
||||
glEnableVertexAttribArray(index++)
|
||||
@ -48,9 +35,7 @@ class HUDFontMesh {
|
||||
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)
|
||||
super.unbind()
|
||||
}
|
||||
|
||||
|
||||
@ -64,15 +49,6 @@ class HUDFontMesh {
|
||||
data.add(Float.fromBits(color.color))
|
||||
}
|
||||
|
||||
fun draw() {
|
||||
glBindVertexArray(vao)
|
||||
glDrawArrays(GL_TRIANGLES, 0, trianglesCount)
|
||||
}
|
||||
|
||||
fun unload() {
|
||||
glDeleteVertexArrays(vao)
|
||||
glDeleteBuffers(vbo)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val FLOATS_PER_VERTEX = 7
|
||||
|
52
src/main/java/de/bixilon/minosoft/gui/rendering/util/Mesh.kt
Normal file
52
src/main/java/de/bixilon/minosoft/gui/rendering/util/Mesh.kt
Normal file
@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.gui.rendering.util
|
||||
|
||||
import org.lwjgl.opengl.GL11.GL_TRIANGLES
|
||||
import org.lwjgl.opengl.GL11.glDrawArrays
|
||||
import org.lwjgl.opengl.GL30.*
|
||||
|
||||
abstract class Mesh {
|
||||
protected val data: MutableList<Float> = mutableListOf()
|
||||
private var vao: Int = 0
|
||||
private var vbo: Int = 0
|
||||
private var trianglesCount: Int = 0
|
||||
|
||||
abstract fun load()
|
||||
|
||||
protected fun initializeBuffers(floatsPerVertex: Int) {
|
||||
trianglesCount = data.size / floatsPerVertex
|
||||
vao = glGenVertexArrays()
|
||||
vbo = glGenBuffers()
|
||||
glBindVertexArray(vao)
|
||||
glBindBuffer(GL_ARRAY_BUFFER, vbo)
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, data.toFloatArray(), GL_STATIC_DRAW)
|
||||
data.clear() // clear data ((do not store in memory)
|
||||
}
|
||||
|
||||
protected fun unbind() {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||
}
|
||||
|
||||
fun draw() {
|
||||
glBindVertexArray(vao)
|
||||
glDrawArrays(GL_TRIANGLES, 0, trianglesCount)
|
||||
}
|
||||
|
||||
fun unload() {
|
||||
glDeleteVertexArrays(vao)
|
||||
glDeleteBuffers(vbo)
|
||||
}
|
||||
}
|
@ -32,7 +32,6 @@ class ScreenshotTaker(
|
||||
fun takeScreenshot() {
|
||||
try {
|
||||
val basePath = "${StaticConfiguration.HOME_DIRECTORY}/screenshots/${renderWindow.connection.address.hostname}/${DATE_FORMATTER.format(System.currentTimeMillis())}"
|
||||
Util.createParentFolderIfNotExist(basePath)
|
||||
var path = "$basePath.png"
|
||||
var i = 1
|
||||
while (File(path).exists()) {
|
||||
@ -56,9 +55,12 @@ class ScreenshotTaker(
|
||||
}
|
||||
}
|
||||
|
||||
ImageIO.write(bufferedImage, "png", File(path))
|
||||
val file = File(path)
|
||||
Util.createParentFolderIfNotExist(file)
|
||||
|
||||
renderWindow.sendDebugMessage("§aScreenshot saved to §f$path")
|
||||
ImageIO.write(bufferedImage, "png", file)
|
||||
|
||||
renderWindow.sendDebugMessage("§aScreenshot saved to §f${file.name}")
|
||||
} catch (exception: Exception) {
|
||||
exception.printStackTrace()
|
||||
renderWindow.sendDebugMessage("§cFailed to make a screenshot!")
|
||||
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
|
||||
*/
|
||||
|
||||
package de.bixilon.minosoft.gui.rendering.util
|
||||
|
||||
import com.google.gson.JsonArray
|
||||
import com.google.gson.JsonElement
|
||||
import com.google.gson.JsonObject
|
||||
import glm_.vec3.Vec3
|
||||
|
||||
object VecUtil {
|
||||
|
||||
fun jsonToVec3(json: JsonElement): Vec3 {
|
||||
when (json) {
|
||||
is JsonArray -> return Vec3(json[0].asFloat, json[1].asFloat, json[2].asFloat)
|
||||
is JsonObject -> TODO()
|
||||
else -> throw IllegalArgumentException("Not a Vec3!")
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user