chunk border renderer

This commit is contained in:
Bixilon 2021-06-13 15:53:02 +02:00 committed by Lukas
parent c1918a1ffd
commit 74f1e1f5d7
9 changed files with 184 additions and 13 deletions

View File

@ -17,6 +17,7 @@ import de.bixilon.minosoft.config.config.game.controls.ControlsGameConfig
import de.bixilon.minosoft.config.config.game.entities.EntitiesConfig import de.bixilon.minosoft.config.config.game.entities.EntitiesConfig
import de.bixilon.minosoft.config.config.game.graphics.GraphicsGameConfig import de.bixilon.minosoft.config.config.game.graphics.GraphicsGameConfig
import de.bixilon.minosoft.config.config.game.sound.SoundConfig import de.bixilon.minosoft.config.config.game.sound.SoundConfig
import de.bixilon.minosoft.config.config.game.world.WorldConfig
import de.bixilon.minosoft.data.mappings.ResourceLocation import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.HUDElement import de.bixilon.minosoft.gui.rendering.hud.elements.primitive.HUDElement
@ -29,4 +30,5 @@ data class GameConfig(
var camera: CameraGameConfig = CameraGameConfig(), var camera: CameraGameConfig = CameraGameConfig(),
var sound: SoundConfig = SoundConfig(), var sound: SoundConfig = SoundConfig(),
var entities: EntitiesConfig = EntitiesConfig(), var entities: EntitiesConfig = EntitiesConfig(),
var world: WorldConfig = WorldConfig(),
) )

View File

@ -0,0 +1,18 @@
/*
* 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.config.config.game.world
data class ChunkBorderConfig(
var enabled: Boolean = false,
)

View File

@ -0,0 +1,20 @@
/*
* 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.config.config.game.world
import com.squareup.moshi.Json
data class WorldConfig(
@Json(name = "chunk_borders") var chunkBorders: ChunkBorderConfig = ChunkBorderConfig(),
)

View File

@ -80,4 +80,6 @@ object RenderConstants {
const val MAX_BLOCK_OUTLINE_RAYCAST_DISTANCE = 5.0f const val MAX_BLOCK_OUTLINE_RAYCAST_DISTANCE = 5.0f
const val MAXIMUM_PARTICLE_AMOUNT = 200000 const val MAXIMUM_PARTICLE_AMOUNT = 200000
const val DEFAULT_LINE_WIDTH = 1.0f / 128.0f
} }

View File

@ -17,6 +17,7 @@ import de.bixilon.minosoft.Minosoft
import de.bixilon.minosoft.config.StaticConfiguration import de.bixilon.minosoft.config.StaticConfiguration
import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames import de.bixilon.minosoft.config.config.game.controls.KeyBindingsNames
import de.bixilon.minosoft.data.registries.ResourceLocation import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.gui.rendering.chunk.ChunkBorderRenderer
import de.bixilon.minosoft.gui.rendering.chunk.WorldRenderer import de.bixilon.minosoft.gui.rendering.chunk.WorldRenderer
import de.bixilon.minosoft.gui.rendering.chunk.block.outline.BlockOutlineRenderer import de.bixilon.minosoft.gui.rendering.chunk.block.outline.BlockOutlineRenderer
import de.bixilon.minosoft.gui.rendering.entities.EntityHitBoxRenderer import de.bixilon.minosoft.gui.rendering.entities.EntityHitBoxRenderer
@ -119,6 +120,9 @@ class RenderWindow(
if (Minosoft.config.config.game.entities.hitBox.enabled) { if (Minosoft.config.config.game.entities.hitBox.enabled) {
registerRenderer(EntityHitBoxRenderer) registerRenderer(EntityHitBoxRenderer)
} }
if (Minosoft.config.config.game.world.chunkBorders.enabled) {
registerRenderer(ChunkBorderRenderer)
}
registerRenderer(HUDRenderer) registerRenderer(HUDRenderer)
} }

View File

@ -0,0 +1,130 @@
/*
* 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.chunk
import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.data.text.ChatColors
import de.bixilon.minosoft.gui.rendering.RenderConstants
import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.Renderer
import de.bixilon.minosoft.gui.rendering.RendererBuilder
import de.bixilon.minosoft.gui.rendering.util.mesh.LineMesh
import de.bixilon.minosoft.protocol.network.connection.PlayConnection
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import glm_.vec2.Vec2i
import glm_.vec3.Vec3
import org.lwjgl.opengl.GL11.*
class ChunkBorderRenderer(
val connection: PlayConnection,
val renderWindow: RenderWindow,
) : Renderer {
private var lastChunkPosition: Vec2i? = null
private var lastMesh: LineMesh? = null
private fun prepare() {
val chunkPosition = renderWindow.connection.player.positionInfo.chunkPosition
if (chunkPosition == lastChunkPosition && lastMesh != null) {
return
}
lastMesh?.unload(false)
val mesh = LineMesh()
val dimension = renderWindow.connection.world.dimension ?: return
val basePosition = chunkPosition * Vec2i(ProtocolDefinition.SECTION_WIDTH_X, ProtocolDefinition.SECTION_WIDTH_Z)
// vertical lines
for (x in 0..ProtocolDefinition.SECTION_WIDTH_X) {
val color = when {
x % ProtocolDefinition.SECTION_WIDTH_X == 0 -> ChatColors.BLUE
x % 2 == 0 -> ChatColors.GREEN
else -> ChatColors.YELLOW
}
mesh.drawLine(Vec3(basePosition.x + x, dimension.minY, basePosition.y), Vec3(basePosition.x + x, dimension.height, basePosition.y), RenderConstants.DEFAULT_LINE_WIDTH * 5, color)
mesh.drawLine(Vec3(basePosition.x + x, dimension.minY, basePosition.y + ProtocolDefinition.SECTION_WIDTH_Z), Vec3(basePosition.x + x, dimension.height, basePosition.y + ProtocolDefinition.SECTION_WIDTH_Z), RenderConstants.DEFAULT_LINE_WIDTH * 5, color)
}
for (z in 0..ProtocolDefinition.SECTION_WIDTH_Z) {
val color = when {
z % ProtocolDefinition.SECTION_WIDTH_Z == 0 -> ChatColors.BLUE
z % 2 == 0 -> ChatColors.GREEN
else -> ChatColors.YELLOW
}
mesh.drawLine(Vec3(basePosition.x, dimension.minY, basePosition.y + z), Vec3(basePosition.x, dimension.height, basePosition.y + z), RenderConstants.DEFAULT_LINE_WIDTH * 5, color)
mesh.drawLine(Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, dimension.minY, basePosition.y + z), Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, dimension.height, basePosition.y + z), RenderConstants.DEFAULT_LINE_WIDTH * 5, color)
}
// horizontal lines
for (y in dimension.minY..dimension.height) {
val borderColor = when {
y % ProtocolDefinition.SECTION_HEIGHT_Y == 0 -> ChatColors.BLUE
y % 2 == 0 -> ChatColors.GREEN
else -> ChatColors.YELLOW
}
// x/z border
mesh.drawLine(Vec3(basePosition.x, y, basePosition.y), Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, y, basePosition.y), RenderConstants.DEFAULT_LINE_WIDTH * 5, borderColor)
mesh.drawLine(Vec3(basePosition.x, y, basePosition.y), Vec3(basePosition.x, y, basePosition.y + ProtocolDefinition.SECTION_WIDTH_Z), RenderConstants.DEFAULT_LINE_WIDTH * 5, borderColor)
mesh.drawLine(Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, y, basePosition.y + ProtocolDefinition.SECTION_WIDTH_Z), Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, y, basePosition.y), RenderConstants.DEFAULT_LINE_WIDTH * 5, borderColor)
mesh.drawLine(Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, y, basePosition.y + ProtocolDefinition.SECTION_WIDTH_Z), Vec3(basePosition.x, y, basePosition.y + ProtocolDefinition.SECTION_WIDTH_Z), RenderConstants.DEFAULT_LINE_WIDTH * 5, borderColor)
if (y % ProtocolDefinition.SECTION_HEIGHT_Y != 0) {
continue
}
for (x in 1..ProtocolDefinition.SECTION_MAX_X) {
val color = when {
x % 2 == 0 -> ChatColors.GREEN
else -> ChatColors.YELLOW
}
mesh.drawLine(Vec3(basePosition.x + x, y, basePosition.y), Vec3(basePosition.x + x, y, basePosition.y + ProtocolDefinition.SECTION_WIDTH_Z), RenderConstants.DEFAULT_LINE_WIDTH * 5, color)
}
for (z in 1..ProtocolDefinition.SECTION_MAX_Z) {
val color = when {
z % 2 == 0 -> ChatColors.GREEN
else -> ChatColors.YELLOW
}
mesh.drawLine(Vec3(basePosition.x, y, basePosition.y + z), Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, y, basePosition.y + z), RenderConstants.DEFAULT_LINE_WIDTH * 5, color)
}
}
mesh.load()
this.lastMesh = mesh
this.lastChunkPosition = chunkPosition
}
override fun draw() {
prepare()
val mesh = lastMesh ?: return
renderWindow.shaderManager.genericColorShader.use()
glDisable(GL_CULL_FACE)
mesh.draw()
glEnable(GL_CULL_FACE)
}
companion object : RendererBuilder<ChunkBorderRenderer> {
override val RESOURCE_LOCATION = ResourceLocation("minosoft:chunk_borders")
override fun build(connection: PlayConnection, renderWindow: RenderWindow): ChunkBorderRenderer {
return ChunkBorderRenderer(connection, renderWindow)
}
}
}

View File

@ -91,11 +91,11 @@ class BlockOutlineRenderer(
val blockOffset = raycastHit.blockPosition.toVec3d + raycastHit.blockPosition.getWorldOffset(raycastHit.blockState.block) val blockOffset = raycastHit.blockPosition.toVec3d + raycastHit.blockPosition.getWorldOffset(raycastHit.blockState.block)
currentMesh.drawVoxelShape(raycastHit.blockState.outlineShape, blockOffset, LINE_WIDTH, Minosoft.config.config.game.other.blockOutline.outlineColor) currentMesh.drawVoxelShape(raycastHit.blockState.outlineShape, blockOffset, RenderConstants.DEFAULT_LINE_WIDTH, Minosoft.config.config.game.other.blockOutline.outlineColor)
if (Minosoft.config.config.game.other.blockOutline.collisionBoxes) { if (Minosoft.config.config.game.other.blockOutline.collisionBoxes) {
currentMesh.drawVoxelShape(raycastHit.blockState.collisionShape, blockOffset, LINE_WIDTH, Minosoft.config.config.game.other.blockOutline.collisionColor, 0.005f) currentMesh.drawVoxelShape(raycastHit.blockState.collisionShape, blockOffset, RenderConstants.DEFAULT_LINE_WIDTH, Minosoft.config.config.game.other.blockOutline.collisionColor, 0.005f)
} }
currentMesh.load() currentMesh.load()
@ -110,7 +110,6 @@ class BlockOutlineRenderer(
companion object : RendererBuilder<BlockOutlineRenderer> { companion object : RendererBuilder<BlockOutlineRenderer> {
override val RESOURCE_LOCATION = ResourceLocation("minosoft:block_outline") override val RESOURCE_LOCATION = ResourceLocation("minosoft:block_outline")
private const val LINE_WIDTH = 1.0f / 128.0f
override fun build(connection: PlayConnection, renderWindow: RenderWindow): BlockOutlineRenderer { override fun build(connection: PlayConnection, renderWindow: RenderWindow): BlockOutlineRenderer {
return BlockOutlineRenderer(connection, renderWindow) return BlockOutlineRenderer(connection, renderWindow)

View File

@ -15,6 +15,7 @@ package de.bixilon.minosoft.gui.rendering.entities
import de.bixilon.minosoft.Minosoft import de.bixilon.minosoft.Minosoft
import de.bixilon.minosoft.data.entities.entities.Entity import de.bixilon.minosoft.data.entities.entities.Entity
import de.bixilon.minosoft.gui.rendering.RenderConstants
import de.bixilon.minosoft.gui.rendering.chunk.models.AABB import de.bixilon.minosoft.gui.rendering.chunk.models.AABB
import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY import de.bixilon.minosoft.gui.rendering.util.VecUtil.EMPTY
import de.bixilon.minosoft.gui.rendering.util.mesh.LineMesh import de.bixilon.minosoft.gui.rendering.util.mesh.LineMesh
@ -33,15 +34,11 @@ class EntityHitBoxMesh(
entity.isInvisible -> Minosoft.config.config.game.entities.hitBox.invisibleEntitiesColor entity.isInvisible -> Minosoft.config.config.game.entities.hitBox.invisibleEntitiesColor
else -> Minosoft.config.config.game.entities.hitBox.hitBoxColor else -> Minosoft.config.config.game.entities.hitBox.hitBoxColor
} }
drawAABB(entity.aabb, Vec3d.EMPTY, LINE_WIDTH, hitBoxColor) drawAABB(entity.aabb, Vec3d.EMPTY, RenderConstants.DEFAULT_LINE_WIDTH, hitBoxColor)
val halfWidth = entity.dimensions.x / 2 val halfWidth = entity.dimensions.x / 2
val eyeAABB = AABB(Vec3(-halfWidth, entity.eyeHeight - LINE_WIDTH, -halfWidth), Vec3(halfWidth, entity.eyeHeight - LINE_WIDTH, halfWidth)).hShrink(LINE_WIDTH) val eyeAABB = AABB(Vec3(-halfWidth, entity.eyeHeight - RenderConstants.DEFAULT_LINE_WIDTH, -halfWidth), Vec3(halfWidth, entity.eyeHeight - RenderConstants.DEFAULT_LINE_WIDTH, halfWidth)).hShrink(RenderConstants.DEFAULT_LINE_WIDTH)
drawAABB(eyeAABB, entity.position, LINE_WIDTH, Minosoft.config.config.game.entities.hitBox.eyeHeightColor) drawAABB(eyeAABB, entity.position, RenderConstants.DEFAULT_LINE_WIDTH, Minosoft.config.config.game.entities.hitBox.eyeHeightColor)
} }
companion object {
private const val LINE_WIDTH = 1.0f / 128.0f
}
} }

View File

@ -92,6 +92,7 @@ class Camera(
} }
yaw %= 180 yaw %= 180
val pitch = glm.clamp(yOffset + entity.rotation.pitch, -89.9, 89.9) val pitch = glm.clamp(yOffset + entity.rotation.pitch, -89.9, 89.9)
entity.rotation = EntityRotation(yaw, pitch)
setRotation(yaw, pitch) setRotation(yaw, pitch)
} }
@ -160,9 +161,7 @@ class Camera(
return glm.lookAt(cameraPosition, cameraPosition + cameraFront, CAMERA_UP_VEC3) return glm.lookAt(cameraPosition, cameraPosition + cameraFront, CAMERA_UP_VEC3)
} }
fun setRotation(yaw: Double, pitch: Double) { private fun setRotation(yaw: Double, pitch: Double) {
entity.rotation = EntityRotation(yaw, pitch)
cameraFront = Vec3d( cameraFront = Vec3d(
(yaw + 90).rad.cos * (-pitch).rad.cos, (yaw + 90).rad.cos * (-pitch).rad.cos,
(-pitch).rad.sin, (-pitch).rad.sin,