mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-12 00:47:26 -04:00
entity visibility manager tests
This commit is contained in:
parent
15b0d653d7
commit
20dd6cbe11
@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Minosoft
|
||||
* Copyright (C) 2020-2023 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.entities.visibility
|
||||
|
||||
import de.bixilon.kotlinglm.vec3.Vec3d
|
||||
import de.bixilon.minosoft.data.entities.EntityRotation
|
||||
import de.bixilon.minosoft.data.entities.data.EntityData
|
||||
import de.bixilon.minosoft.data.entities.entities.Entity
|
||||
import de.bixilon.minosoft.data.entities.entities.animal.Pig
|
||||
import de.bixilon.minosoft.gui.rendering.entities.EntityRendererTestUtil
|
||||
import de.bixilon.minosoft.gui.rendering.entities.feature.EntityRenderFeature
|
||||
import de.bixilon.minosoft.gui.rendering.entities.renderer.EntityRenderer
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
||||
import org.testng.Assert.assertEquals
|
||||
import org.testng.annotations.Test
|
||||
|
||||
@Test(groups = ["entities", "rendering"])
|
||||
class VisibilityManagerTest {
|
||||
|
||||
private fun create(): VisibilityManager {
|
||||
val renderer = EntityRendererTestUtil.create()
|
||||
return VisibilityManager(renderer)
|
||||
}
|
||||
|
||||
private fun VisibilityManager.entity(): Entity {
|
||||
return Pig(renderer.connection, EntityRendererTestUtil.PIG, EntityData(renderer.connection, Int2ObjectOpenHashMap()), Vec3d(), EntityRotation.EMPTY)
|
||||
}
|
||||
|
||||
private fun VisibilityManager.feature(layer: EntityLayer, priority: Int = 0, distance: Double = 0.0) = object : EntityRenderer<Entity>(this.renderer, entity()) {
|
||||
|
||||
val f = object : EntityRenderFeature(this) {
|
||||
override val layer = layer
|
||||
override val priority = priority
|
||||
|
||||
override fun draw() = Unit
|
||||
}
|
||||
|
||||
init {
|
||||
features.clear()
|
||||
features += f
|
||||
this.distance = distance
|
||||
}
|
||||
|
||||
override fun toString(): String {
|
||||
return "feature"
|
||||
}
|
||||
}
|
||||
|
||||
fun `no features`() {
|
||||
val visibility = create()
|
||||
visibility.finish()
|
||||
assertEquals(visibility.opaque.size, 0)
|
||||
assertEquals(visibility.translucent.size, 0)
|
||||
}
|
||||
|
||||
fun `single opaque features`() {
|
||||
val visibility = create()
|
||||
val feature = visibility.feature(EntityLayer.Opaque)
|
||||
visibility.collect(feature)
|
||||
visibility.finish()
|
||||
assertEquals(visibility.opaque, listOf(feature.f))
|
||||
assertEquals(visibility.translucent.size, 0)
|
||||
}
|
||||
|
||||
fun `single translucent features`() {
|
||||
val visibility = create()
|
||||
val feature = visibility.feature(EntityLayer.Translucent)
|
||||
visibility.collect(feature)
|
||||
visibility.finish()
|
||||
assertEquals(visibility.opaque.size, 0)
|
||||
assertEquals(visibility.translucent, listOf(feature.f))
|
||||
}
|
||||
|
||||
fun `two opaque features, sorted by distance`() {
|
||||
val visibility = create()
|
||||
val a = visibility.feature(EntityLayer.Opaque, priority = 0, 0.0)
|
||||
val b = visibility.feature(EntityLayer.Opaque, priority = 0, 1.0)
|
||||
visibility.collect(a); visibility.collect(b)
|
||||
visibility.finish()
|
||||
assertEquals(visibility.opaque, listOf(a.f, b.f))
|
||||
}
|
||||
|
||||
fun `two translucent features, sorted by distance`() {
|
||||
val visibility = create()
|
||||
val a = visibility.feature(EntityLayer.Translucent, priority = 0, 0.0)
|
||||
val b = visibility.feature(EntityLayer.Translucent, priority = 0, 1.0)
|
||||
visibility.collect(a); visibility.collect(b)
|
||||
visibility.finish()
|
||||
assertEquals(visibility.translucent, listOf(b.f, a.f))
|
||||
}
|
||||
|
||||
fun `two translucent features, sorted by type`() {
|
||||
val visibility = create()
|
||||
val a = visibility.feature(EntityLayer.Translucent, priority = 1, 0.0)
|
||||
val b = visibility.feature(EntityLayer.Translucent, priority = 0, 0.0)
|
||||
visibility.collect(a); visibility.collect(b)
|
||||
visibility.finish()
|
||||
assertEquals(visibility.translucent, listOf(b.f, a.f))
|
||||
}
|
||||
|
||||
fun `sorted by type and distance`() {
|
||||
val visibility = create()
|
||||
val a = visibility.feature(EntityLayer.Opaque, priority = 1, 0.0)
|
||||
val b = visibility.feature(EntityLayer.Opaque, priority = 0, 0.0)
|
||||
val c = visibility.feature(EntityLayer.Opaque, priority = 0, 5.0)
|
||||
val d = visibility.feature(EntityLayer.Opaque, priority = 0, 2.0)
|
||||
val e = visibility.feature(EntityLayer.Opaque, priority = 1, 2.0)
|
||||
visibility.collect(a); visibility.collect(b); visibility.collect(c); visibility.collect(d); visibility.collect(e)
|
||||
visibility.finish()
|
||||
assertEquals(visibility.opaque, listOf(b.f, d.f, c.f, a.f, e.f))
|
||||
}
|
||||
}
|
@ -46,8 +46,8 @@ class EntitiesRenderer(
|
||||
private var reset = false
|
||||
|
||||
override fun registerLayers() {
|
||||
layers.register(EntityLayer.OpaqueEntityLayer, null, { visibility.opaque.draw() }) { visibility.opaque.size <= 0 }
|
||||
layers.register(EntityLayer.TranslucentEntityLayer, null, { visibility.translucent.draw() }) { visibility.opaque.size <= 0 }
|
||||
layers.register(EntityLayer.Opaque, null, { visibility.opaque.draw() }) { visibility.opaque.size <= 0 }
|
||||
layers.register(EntityLayer.Translucent, null, { visibility.translucent.draw() }) { visibility.opaque.size <= 0 }
|
||||
}
|
||||
|
||||
override fun prePrepareDraw() {
|
||||
|
@ -23,7 +23,7 @@ abstract class EntityRenderFeature(val renderer: EntityRenderer<*>) : Comparable
|
||||
open val priority: Int get() = 0
|
||||
val sort = this::class.java.hashCode()
|
||||
|
||||
open val layer: EntityLayer get() = EntityLayer.OpaqueEntityLayer
|
||||
open val layer: EntityLayer get() = EntityLayer.Opaque
|
||||
|
||||
open fun updateVisibility(occluded: Boolean) {
|
||||
this.visible = !occluded
|
||||
@ -37,7 +37,7 @@ abstract class EntityRenderFeature(val renderer: EntityRenderer<*>) : Comparable
|
||||
|
||||
open fun compareByDistance(other: EntityRenderFeature): Int {
|
||||
val compared = renderer.distance.compareTo(other.renderer.distance)
|
||||
if (layer === EntityLayer.TranslucentEntityLayer) return -compared // translucent is sorted the exact other way
|
||||
if (layer === EntityLayer.Translucent) return -compared // translucent is sorted the exact other way
|
||||
return compared
|
||||
}
|
||||
|
||||
|
@ -53,6 +53,10 @@ class FeatureManager(val renderer: EntityRenderer<*>) : Iterable<EntityRenderFea
|
||||
}
|
||||
}
|
||||
|
||||
fun clear() {
|
||||
features.clear()
|
||||
}
|
||||
|
||||
|
||||
override fun iterator(): Iterator<EntityRenderFeature> {
|
||||
return features.iterator()
|
||||
|
@ -27,6 +27,7 @@ import de.bixilon.minosoft.gui.rendering.font.renderer.element.TextRenderInfo
|
||||
import de.bixilon.minosoft.gui.rendering.font.renderer.element.TextRenderProperties
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.BlendingFunctions
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.DepthFunctions
|
||||
import de.bixilon.minosoft.gui.rendering.util.mat.mat4.Mat4Util.reset
|
||||
import de.bixilon.minosoft.gui.rendering.util.mat.mat4.Mat4Util.translateXAssign
|
||||
import de.bixilon.minosoft.gui.rendering.util.mat.mat4.Mat4Util.translateYAssign
|
||||
import de.bixilon.minosoft.gui.rendering.util.mesh.Mesh
|
||||
@ -55,10 +56,9 @@ open class BillboardTextFeature(
|
||||
set(value) {
|
||||
if (field == value) return
|
||||
field = value
|
||||
unload() // TODO: just update matrix
|
||||
}
|
||||
|
||||
override val layer get() = EntityLayer.TranslucentEntityLayer
|
||||
override val layer get() = EntityLayer.Translucent
|
||||
|
||||
override fun update(millis: Long, delta: Float) {
|
||||
if (!super.enabled) return unload()
|
||||
@ -84,9 +84,11 @@ open class BillboardTextFeature(
|
||||
}
|
||||
|
||||
private fun updateMatrix() {
|
||||
// TODO: update matrix only on demand (and maybe do the camera rotation somewhere else and cached)
|
||||
val width = this.info?.size?.x ?: return
|
||||
val mat = renderer.renderer.context.camera.view.view.rotation
|
||||
val matrix = Mat4()
|
||||
this.matrix.reset()
|
||||
this.matrix
|
||||
.translateYAssign(renderer.entity.dimensions.y + offset)
|
||||
.rotateYassign((EntityRotation.HALF_CIRCLE_DEGREE - mat.yaw).rad)
|
||||
.rotateXassign((180.0f - mat.pitch).rad)
|
||||
|
@ -16,17 +16,16 @@ package de.bixilon.minosoft.gui.rendering.entities.visibility
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.layer.OpaqueLayer
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.layer.RenderLayer
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.layer.TranslucentLayer
|
||||
import de.bixilon.minosoft.gui.rendering.system.base.settings.RenderSettings
|
||||
|
||||
interface EntityLayer : RenderLayer {
|
||||
|
||||
object OpaqueEntityLayer : EntityLayer {
|
||||
override val settings = RenderSettings(faceCulling = false)
|
||||
object Opaque : EntityLayer {
|
||||
override val settings = OpaqueLayer.settings.copy(faceCulling = false)
|
||||
override val priority: Int get() = OpaqueLayer.priority + 1 // entities are mostly more expensive to render, let the gpu clip all fragments first
|
||||
}
|
||||
|
||||
object TranslucentEntityLayer : EntityLayer {
|
||||
override val settings = RenderSettings(faceCulling = false)
|
||||
object Translucent : EntityLayer {
|
||||
override val settings = TranslucentLayer.settings.copy(faceCulling = false)
|
||||
override val priority: Int get() = TranslucentLayer.priority - 1 // otherwise not visible through water, etc
|
||||
}
|
||||
}
|
||||
|
@ -75,8 +75,8 @@ class VisibilityManager(val renderer: EntitiesRenderer) {
|
||||
}
|
||||
|
||||
operator fun get(layer: EntityLayer) = when (layer) {
|
||||
EntityLayer.OpaqueEntityLayer -> opaque
|
||||
EntityLayer.TranslucentEntityLayer -> translucent
|
||||
EntityLayer.Opaque -> opaque
|
||||
EntityLayer.Translucent -> translucent
|
||||
else -> throw IllegalStateException("Unknown entity layer: $layer")
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user