mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-14 18:05:51 -04:00
improve raycasting block outline
This commit is contained in:
parent
f1e3051f4e
commit
4311eaabaa
@ -115,7 +115,7 @@ class World : BiomeAccessor {
|
||||
return blocks.toMap()
|
||||
}
|
||||
|
||||
data class RayCastHit(
|
||||
data class RaycastHit(
|
||||
val position: Vec3,
|
||||
val distance: Float,
|
||||
val blockState: BlockState,
|
||||
@ -124,7 +124,7 @@ class World : BiomeAccessor {
|
||||
val blockPosition = position.floor
|
||||
}
|
||||
|
||||
fun raycast(origin: Vec3, direction: Vec3): RayCastHit? {
|
||||
fun raycast(origin: Vec3, direction: Vec3): RaycastHit? {
|
||||
val currentPosition = Vec3(origin)
|
||||
|
||||
fun getTotalDistance(): Float {
|
||||
@ -140,7 +140,7 @@ class World : BiomeAccessor {
|
||||
} ?: -1.0f
|
||||
|
||||
if (distance >= 0.0f && blockState != null) {
|
||||
return RayCastHit(
|
||||
return RaycastHit(
|
||||
currentPosition + direction * distance,
|
||||
getTotalDistance() + distance,
|
||||
blockState = blockState,
|
||||
|
@ -303,7 +303,7 @@ class Camera(
|
||||
cameraPosition = getAbsoluteCameraPosition()
|
||||
}
|
||||
|
||||
fun getTargetBlock(): World.RayCastHit? {
|
||||
fun getTargetBlock(): World.RaycastHit? {
|
||||
return connection.world.raycast(cameraPosition, cameraFront)
|
||||
}
|
||||
|
||||
|
@ -76,4 +76,6 @@ object RenderConstants {
|
||||
|
||||
const val DOUBLE_PRESS_KEY_PRESS_MAX_DELAY = 200
|
||||
const val DOUBLE_PRESS_DELAY_BETWEEN_PRESSED = 500
|
||||
|
||||
const val MAX_BLOCK_OUTLINE_RAYCAST_DISTANCE = 5.0f
|
||||
}
|
||||
|
@ -111,7 +111,7 @@ class WorldRenderer(
|
||||
}
|
||||
}
|
||||
|
||||
if (meshCollection.transparentSectionArrayMesh!!.trianglesCount == 0) {
|
||||
if (meshCollection.transparentSectionArrayMesh!!.primitiveCount == 0) {
|
||||
meshCollection.transparentSectionArrayMesh = null
|
||||
}
|
||||
|
||||
@ -321,24 +321,24 @@ class WorldRenderer(
|
||||
sectionMap[index]?.let {
|
||||
it.opaqueSectionArrayMesh.unload()
|
||||
meshes--
|
||||
triangles -= it.opaqueSectionArrayMesh.trianglesCount
|
||||
triangles -= it.opaqueSectionArrayMesh.primitiveCount
|
||||
|
||||
it.transparentSectionArrayMesh?.let {
|
||||
it.unload()
|
||||
meshes--
|
||||
triangles -= it.trianglesCount
|
||||
triangles -= it.primitiveCount
|
||||
}
|
||||
}
|
||||
|
||||
meshCollection.opaqueSectionArrayMesh.let {
|
||||
it.load()
|
||||
meshes++
|
||||
triangles += it.trianglesCount
|
||||
triangles += it.primitiveCount
|
||||
}
|
||||
meshCollection.transparentSectionArrayMesh?.let {
|
||||
it.load()
|
||||
meshes++
|
||||
triangles += it.trianglesCount
|
||||
triangles += it.primitiveCount
|
||||
}
|
||||
|
||||
|
||||
@ -390,12 +390,12 @@ class WorldRenderer(
|
||||
meshCollection.opaqueSectionArrayMesh.let {
|
||||
it.unload()
|
||||
this.meshes--
|
||||
triangles -= it.trianglesCount
|
||||
triangles -= it.primitiveCount
|
||||
}
|
||||
meshCollection.transparentSectionArrayMesh?.let {
|
||||
it.unload()
|
||||
this.meshes--
|
||||
triangles -= it.trianglesCount
|
||||
triangles -= it.primitiveCount
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import org.lwjgl.opengl.GL20.glEnableVertexAttribArray
|
||||
import org.lwjgl.opengl.GL20.glVertexAttribPointer
|
||||
|
||||
class BlockOutlineMesh : Mesh() {
|
||||
|
||||
fun addVertex(position: Vec3) {
|
||||
data.addAll(floatArrayOf(
|
||||
position.x,
|
||||
@ -37,6 +38,7 @@ class BlockOutlineMesh : Mesh() {
|
||||
super.unbind()
|
||||
}
|
||||
|
||||
|
||||
companion object {
|
||||
private const val FLOATS_PER_VERTEX = 3
|
||||
}
|
||||
|
@ -13,9 +13,11 @@
|
||||
|
||||
package de.bixilon.minosoft.gui.rendering.chunk.block.outline
|
||||
|
||||
import de.bixilon.minosoft.data.Gamemodes
|
||||
import de.bixilon.minosoft.data.mappings.ResourceLocation
|
||||
import de.bixilon.minosoft.data.mappings.blocks.BlockState
|
||||
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
|
||||
@ -26,7 +28,7 @@ import de.bixilon.minosoft.protocol.network.connection.PlayConnection
|
||||
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
|
||||
import glm_.vec3.Vec3
|
||||
import glm_.vec3.Vec3i
|
||||
import org.lwjgl.opengl.GL11
|
||||
import org.lwjgl.opengl.GL11.*
|
||||
|
||||
class BlockOutlineRenderer(
|
||||
val connection: PlayConnection,
|
||||
@ -61,17 +63,19 @@ class BlockOutlineRenderer(
|
||||
for (aabb in shape) {
|
||||
val min = blockPosition + aabb.min
|
||||
val max = blockPosition + aabb.max
|
||||
|
||||
fun drawSideQuad(x: Float) {
|
||||
drawLine(Vec3(x, min.y, min.z), Vec3(x, max.y, min.z), mesh)
|
||||
drawLine(Vec3(x, min.y, min.z), Vec3(x, min.y, max.z), mesh)
|
||||
drawLine(Vec3(x, max.y, min.z), Vec3(x, max.y, max.z), mesh)
|
||||
drawLine(Vec3(x, min.y, max.z), Vec3(x, max.y, max.z), mesh)
|
||||
}
|
||||
|
||||
// left quad
|
||||
drawLine(Vec3(min.x, min.y, min.z), Vec3(min.x, max.y, min.z), mesh)
|
||||
drawLine(Vec3(min.x, min.y, min.z), Vec3(min.x, min.y, max.z), mesh)
|
||||
drawLine(Vec3(min.x, max.y, min.z), Vec3(min.x, max.y, max.z), mesh)
|
||||
drawLine(Vec3(min.x, min.y, max.z), Vec3(min.x, max.y, max.z), mesh)
|
||||
drawSideQuad(min.x)
|
||||
|
||||
// right quad
|
||||
drawLine(Vec3(max.x, min.y, min.z), Vec3(max.x, max.y, min.z), mesh)
|
||||
drawLine(Vec3(max.x, min.y, min.z), Vec3(max.x, min.y, max.z), mesh)
|
||||
drawLine(Vec3(max.x, max.y, min.z), Vec3(max.x, max.y, max.z), mesh)
|
||||
drawLine(Vec3(max.x, min.y, max.z), Vec3(max.x, max.y, max.z), mesh)
|
||||
drawSideQuad(max.x)
|
||||
|
||||
// connections between 2 quads
|
||||
drawLine(Vec3(min.x, min.y, min.z), Vec3(max.x, min.y, min.z), mesh)
|
||||
@ -82,28 +86,45 @@ class BlockOutlineRenderer(
|
||||
}
|
||||
|
||||
private fun draw(mesh: BlockOutlineMesh) {
|
||||
GL11.glDisable(GL11.GL_CULL_FACE)
|
||||
glDisable(GL_CULL_FACE)
|
||||
outlineShader.use()
|
||||
mesh.draw()
|
||||
GL11.glEnable(GL11.GL_CULL_FACE)
|
||||
glEnable(GL_CULL_FACE)
|
||||
}
|
||||
|
||||
private fun unload() {
|
||||
outlineMesh ?: return
|
||||
outlineMesh?.unload()
|
||||
this.outlineMesh = null
|
||||
this.currentOutlinePosition = null
|
||||
this.currentOutlineBlockState = null
|
||||
}
|
||||
|
||||
override fun draw() {
|
||||
val rayCastHit = renderWindow.inputHandler.camera.getTargetBlock()
|
||||
val raycastHit = renderWindow.inputHandler.camera.getTargetBlock()
|
||||
|
||||
var outlineMesh = outlineMesh
|
||||
|
||||
|
||||
if (rayCastHit == null) {
|
||||
outlineMesh ?: return
|
||||
outlineMesh.unload()
|
||||
this.outlineMesh = null
|
||||
this.currentOutlinePosition = null
|
||||
this.currentOutlineBlockState = null
|
||||
|
||||
if (raycastHit == null) {
|
||||
unload()
|
||||
return
|
||||
}
|
||||
|
||||
if (rayCastHit.blockPosition == currentOutlinePosition && rayCastHit.blockState == currentOutlineBlockState) {
|
||||
if (raycastHit.distance >= RenderConstants.MAX_BLOCK_OUTLINE_RAYCAST_DISTANCE) {
|
||||
unload()
|
||||
return
|
||||
}
|
||||
|
||||
if (connection.player.entity.gamemode == Gamemodes.ADVENTURE || connection.player.entity.gamemode == Gamemodes.SPECTATOR) {
|
||||
if (connection.mapping.blockEntityRegistry.get(raycastHit.blockState.block.resourceLocation) == null) {
|
||||
unload()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if (raycastHit.blockPosition == currentOutlinePosition && raycastHit.blockState == currentOutlineBlockState) {
|
||||
draw(outlineMesh!!)
|
||||
return
|
||||
}
|
||||
@ -111,11 +132,11 @@ class BlockOutlineRenderer(
|
||||
outlineMesh?.unload()
|
||||
outlineMesh = BlockOutlineMesh()
|
||||
|
||||
drawVoxelShape(rayCastHit.blockState.outlineShape, rayCastHit.blockPosition.getWorldOffset(rayCastHit.blockState.block).plus(rayCastHit.blockPosition), outlineMesh)
|
||||
drawVoxelShape(raycastHit.blockState.outlineShape, raycastHit.blockPosition.getWorldOffset(raycastHit.blockState.block).plus(raycastHit.blockPosition), outlineMesh)
|
||||
outlineMesh.load()
|
||||
|
||||
this.currentOutlinePosition = rayCastHit.blockPosition
|
||||
this.currentOutlineBlockState = rayCastHit.blockState
|
||||
this.currentOutlinePosition = raycastHit.blockPosition
|
||||
this.currentOutlineBlockState = raycastHit.blockState
|
||||
this.outlineMesh = outlineMesh
|
||||
draw(outlineMesh)
|
||||
}
|
||||
@ -123,7 +144,7 @@ class BlockOutlineRenderer(
|
||||
|
||||
companion object : RendererBuilder<BlockOutlineRenderer> {
|
||||
override val RESOURCE_LOCATION = ResourceLocation("minosoft:block_outline")
|
||||
private const val LINE_WIDTH = 1.0f / 16.0f
|
||||
private const val LINE_WIDTH = 1.0f / 64.0f
|
||||
private const val HALF_LINE_WIDTH = LINE_WIDTH / 2.0f
|
||||
|
||||
override fun build(connection: PlayConnection, renderWindow: RenderWindow): BlockOutlineRenderer {
|
||||
|
@ -87,10 +87,10 @@ class HUDSystemDebugNode(hudRenderer: HUDRenderer) : DebugScreenNode(hudRenderer
|
||||
allocatedMemoryText.sText = "Allocated: ${getAllocatedMemoryPercent()}% ${getFormattedAllocatedMemory()}"
|
||||
val rayCastHit = hudRenderer.renderWindow.inputHandler.camera.getTargetBlock()
|
||||
if (rayCastHit == null) {
|
||||
targetPosition.sText = "No blocks in reach!"
|
||||
targetPosition.sText = ""
|
||||
targetBlockState.sText = ""
|
||||
} else {
|
||||
targetPosition.sText = "looking at ${rayCastHit.blockPosition}"
|
||||
targetPosition.sText = "Target block: ${rayCastHit.blockPosition}"
|
||||
targetBlockState.sText = rayCastHit.blockState.toString()
|
||||
}
|
||||
|
||||
|
@ -28,9 +28,10 @@ abstract class Mesh(
|
||||
_data = value
|
||||
}
|
||||
|
||||
private var vao: Int = -1
|
||||
protected var vao: Int = -1
|
||||
private set
|
||||
private var vbo: Int = -1
|
||||
var trianglesCount: Int = -1
|
||||
var primitiveCount: Int = -1
|
||||
private set
|
||||
|
||||
var state = MeshStates.PREPARING
|
||||
@ -42,7 +43,7 @@ abstract class Mesh(
|
||||
protected fun initializeBuffers(floatsPerVertex: Int) {
|
||||
check(state == MeshStates.PREPARING) { "Mesh already loaded: $state" }
|
||||
|
||||
trianglesCount = data.size / floatsPerVertex
|
||||
primitiveCount = data.size / floatsPerVertex
|
||||
vao = glGenVertexArrays()
|
||||
vbo = glGenBuffers()
|
||||
glBindVertexArray(vao)
|
||||
@ -58,10 +59,10 @@ abstract class Mesh(
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
||||
}
|
||||
|
||||
fun draw() {
|
||||
open fun draw() {
|
||||
// check(state == MeshStates.LOADED) { "Mesh not loaded: $state" }
|
||||
glBindVertexArray(vao)
|
||||
glDrawArrays(GL_TRIANGLES, 0, trianglesCount)
|
||||
glDrawArrays(GL_TRIANGLES, 0, primitiveCount)
|
||||
}
|
||||
|
||||
fun unload(checkLoaded: Boolean = true) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user