From 2c732f44d065739e7965fbd9bea7b34ace8095e5 Mon Sep 17 00:00:00 2001 From: Moritz Zwerger Date: Tue, 24 Oct 2023 18:13:16 +0200 Subject: [PATCH] improved hitbox rendering --- doc/rendering/Entities.md | 26 +++++-- .../rendering/entities/hitbox/HitboxData.kt | 18 +++-- .../entities/hitbox/HitboxFeature.kt | 73 ++++++++++++++++++- .../entities/hitbox/HitboxManager.kt | 4 +- .../entities/visibility/EntityVisibility.kt | 1 - 5 files changed, 102 insertions(+), 20 deletions(-) diff --git a/doc/rendering/Entities.md b/doc/rendering/Entities.md index 0abb7afe3..5f3ba57cf 100644 --- a/doc/rendering/Entities.md +++ b/doc/rendering/Entities.md @@ -44,26 +44,36 @@ Entities are always designed without any rotation (i.e. `yaw`=`0`) ## General - render layers (opaque -> transparent -> translucent -> ...) (but face culling enabled) - - sort in layers after distance (or -distance) - - there are also invisible renderers (like AreaEffectCloud is just emitting particles) + - sort in layers after distance (or -distance) + - there are also invisible renderers (like AreaEffectCloud is just emitting particles) - update all models async (with their visibility, etc) - queue for unloading and loading meshes before draw (better while async preparing to save time. Maybe port that system to block entities) - Loop over all visible entity renderers and work on the entity layer as needed - update visible and not visible - - entity name is also visible through walls, rest not - - also with frustum (no need to update renderers that are out of the frustum) + - entity name is also visible through walls, rest not + - also with frustum (no need to update renderers that are out of the frustum) + - -> handle occlusion differently from visibility - option to turn on/off "features" - how to register entity models? - - loop over all entity (and block entity) types and register? + - loop over all entity (and block entity) types and register? +- store entities in octree like structure + - ways faster collisions with them -> physics + - way faster getInRadius -> particles, maybe entities in the future ## Hitboxes - Create line mesh with default aabb - - interpolate aabb if size changes (e.g. changing pose for players) - - how about rendering velocity or view? + - interpolate + - aabb (not at all, taken from renderInfo) + - color: 0.5s + - velocity (ticks) + - direction (taken from renderInfo) + - eye height (taken from renderInfo) + - they must alight with the matrix handler -> mustn't be a frame too late/early - Store offset and rotation as uniform - Make hitbox a default feature of entity renderer -- draw as opaque +- highest priority (enables cheap gpu clipping) +- dynamic enabling and disabling (hitbox manager, keybinding) ## Tests diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/hitbox/HitboxData.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/hitbox/HitboxData.kt index ec75cb87c..26f0204ac 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/hitbox/HitboxData.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/hitbox/HitboxData.kt @@ -14,13 +14,17 @@ package de.bixilon.minosoft.gui.rendering.entities.hitbox import de.bixilon.kotlinglm.vec3.Vec3 -import de.bixilon.minosoft.data.entities.EntityRotation -import de.bixilon.minosoft.data.registries.shapes.aabb.AABB +import de.bixilon.minosoft.data.entities.entities.Entity +import de.bixilon.minosoft.data.text.formatting.color.ChatColors import de.bixilon.minosoft.data.text.formatting.color.RGBColor +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY_INSTANCE data class HitboxData( - val aabb: AABB, - val color: RGBColor, - val velocity: Vec3?, - val rotation: EntityRotation, -) + var color: RGBColor = ChatColors.WHITE, + var velocity: Vec3 = Vec3.EMPTY_INSTANCE, +) { + + fun update(entity: Entity) { + + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/hitbox/HitboxFeature.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/hitbox/HitboxFeature.kt index bcadf3e96..1bbeacc81 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/hitbox/HitboxFeature.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/hitbox/HitboxFeature.kt @@ -13,31 +13,98 @@ package de.bixilon.minosoft.gui.rendering.entities.hitbox +import de.bixilon.kotlinglm.vec3.Vec3 +import de.bixilon.kotlinglm.vec3.Vec3i +import de.bixilon.minosoft.data.entities.EntityRotation +import de.bixilon.minosoft.data.registries.shapes.aabb.AABB import de.bixilon.minosoft.data.text.formatting.color.ChatColors import de.bixilon.minosoft.gui.rendering.entities.feature.EntityRenderFeature import de.bixilon.minosoft.gui.rendering.entities.renderer.EntityRenderer import de.bixilon.minosoft.gui.rendering.util.mesh.LineMesh import de.bixilon.minosoft.gui.rendering.util.mesh.Mesh +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY class HitboxFeature(renderer: EntityRenderer<*>) : EntityRenderFeature(renderer) { - private val shader = renderer.renderer.context.shaders.genericColorShader + private val manager = renderer.renderer.hitbox private var mesh: LineMesh? = null + private var aabb = AABB.EMPTY + private var eyePosition = Vec3.EMPTY + private var rotation = EntityRotation.EMPTY + + private val data = HitboxData() + private var data0 = HitboxData() + private var data1 = HitboxData() + + override fun reset() { unload() } override fun update(millis: Long) { + if (!manager.enabled) return unload() + + val offset = renderer.renderer.context.camera.offset.offset + + val update = updateRenderInfo(offset) or interpolate(millis) + + if (this.mesh != null && !update) return + + updateMesh() + } + + + private fun updateRenderInfo(offset: Vec3i): Boolean { + var changes = 0 + + val renderInfo = renderer.entity.renderInfo + val aabb = renderInfo.cameraAABB + -offset + val eyePosition = Vec3(renderInfo.eyePosition - offset) + val rotation = renderInfo.rotation + + if (aabb != this.aabb) { + this.aabb = aabb; changes++ + } + if (eyePosition != this.eyePosition) { + this.eyePosition = eyePosition; changes++ + } + if (rotation != this.rotation) { + this.rotation = rotation; changes++ + } + + return changes > 0 + } + + private fun interpolate(millis: Long): Boolean { + // TODO: interpolate color in 5 ticks and velocity per tick + return false + } + + private fun updateMesh() { unload() val mesh = LineMesh(renderer.renderer.context) - mesh.drawLazyAABB(renderer.entity.renderInfo.cameraAABB, renderer.entity.hitboxColor ?: ChatColors.WHITE) + + if (manager.profile.lazy) { + mesh.drawLazyAABB(aabb, data.color) + } else { + mesh.drawAABB(aabb, color = data.color) + } + + val center = Vec3(aabb.center) + if (data.velocity.length2() > 0.003f) { + mesh.drawLine(center, center + data.velocity * 15.0f, color = ChatColors.YELLOW) + } + + mesh.drawLine(eyePosition, eyePosition + rotation.front * 5.0f, color = ChatColors.BLUE) + + this.mesh = mesh } override fun draw() { val mesh = this.mesh ?: return if (mesh.state != Mesh.MeshStates.LOADED) mesh.load() - shader.use() + manager.shader.use() mesh.draw() } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/hitbox/HitboxManager.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/hitbox/HitboxManager.kt index 400466dd1..77ad38c5c 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/hitbox/HitboxManager.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/hitbox/HitboxManager.kt @@ -22,7 +22,9 @@ import de.bixilon.minosoft.gui.rendering.entities.EntitiesRenderer import de.bixilon.minosoft.util.KUtil.format class HitboxManager(private val renderer: EntitiesRenderer) { - private val profile = renderer.profile.hitbox + val profile = renderer.profile.hitbox + val shader = renderer.context.shaders.genericColorShader + var enabled = profile.enabled diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/visibility/EntityVisibility.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/visibility/EntityVisibility.kt index 026fb196f..8c378b940 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/visibility/EntityVisibility.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/visibility/EntityVisibility.kt @@ -19,6 +19,5 @@ class EntityVisibility(val renderer: EntityRenderer<*>) { val visible: Boolean = true fun update(force: Boolean) { - TODO() } }