entity render distance

This commit is contained in:
Moritz Zwerger 2023-11-13 15:04:14 +01:00
parent b0d99a011a
commit cc92897293
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
5 changed files with 71 additions and 11 deletions

View File

@ -19,6 +19,7 @@ import de.bixilon.minosoft.config.profile.delegate.types.StringDelegate
import de.bixilon.minosoft.config.profile.profiles.Profile
import de.bixilon.minosoft.config.profile.profiles.entity.EntityProfileManager.latestVersion
import de.bixilon.minosoft.config.profile.profiles.entity.features.FeaturesC
import de.bixilon.minosoft.config.profile.profiles.entity.general.GeneralC
import java.util.concurrent.atomic.AtomicInteger
/**
@ -37,6 +38,7 @@ class EntityProfile(
override var description by StringDelegate(this, description ?: "")
val general = GeneralC(this)
val features = FeaturesC(this)
override fun toString(): String {

View File

@ -0,0 +1,32 @@
/*
* 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.config.profile.profiles.entity.general
import de.bixilon.minosoft.config.profile.delegate.primitive.BooleanDelegate
import de.bixilon.minosoft.config.profile.delegate.primitive.IntDelegate
import de.bixilon.minosoft.config.profile.profiles.entity.EntityProfile
import de.bixilon.minosoft.data.world.World
class GeneralC(profile: EntityProfile) {
/**
* Enables entity rendering
*/
var enabled by BooleanDelegate(profile, true)
/**
* Entity render distance (x,y,z direction)
* May be -1 to use the block render distance
*/
var renderDistance by IntDelegate(profile, -1, "", ranges = arrayOf(-1..-1, 0..World.MAX_RENDER_DISTANCE))
}

View File

@ -60,7 +60,8 @@ class EntitiesRenderer(
this.visibility.reset()
renderers.iterate {
if (reset) it.reset()
visibility.update(it)
visibility.update(it, millis)
if (!it.visible) return@iterate
it.update(millis)
visibility.collect(it)
}
@ -91,7 +92,8 @@ class EntitiesRenderer(
companion object : RendererBuilder<EntitiesRenderer> {
override fun build(connection: PlayConnection, context: RenderContext): EntitiesRenderer {
override fun build(connection: PlayConnection, context: RenderContext): EntitiesRenderer? {
if (!connection.profiles.entity.general.enabled) return null
return EntitiesRenderer(connection, context)
}
}

View File

@ -72,12 +72,16 @@ abstract class EntityRenderer<E : Entity>(
open fun update(millis: Long, delta: Float) {
updateLight(delta)
entity.draw(millis)
this.distance = (entity.renderInfo.eyePosition - renderer.connection.camera.entity.renderInfo.eyePosition).length2()
updateRenderInfo(millis)
updateMatrix(delta)
features.update(millis, delta)
}
open fun updateRenderInfo(millis: Long) {
entity.draw(millis)
this.distance = (entity.renderInfo.eyePosition - renderer.connection.camera.entity.renderInfo.eyePosition).length2()
}
private fun getCurrentLight(): Int {
var light = entity.physics.positionInfo.chunk?.light?.get(entity.physics.positionInfo.inChunkPosition) ?: return 0xFF
if (entity.isOnFire) {

View File

@ -14,37 +14,58 @@
package de.bixilon.minosoft.gui.rendering.entities.visibility
import de.bixilon.kutil.concurrent.lock.simple.SimpleLock
import de.bixilon.kutil.observer.DataObserver.Companion.observe
import de.bixilon.minosoft.data.world.view.ViewDistanceChangeEvent
import de.bixilon.minosoft.gui.rendering.entities.EntitiesRenderer
import de.bixilon.minosoft.gui.rendering.entities.feature.EntityRenderFeature
import de.bixilon.minosoft.gui.rendering.entities.renderer.EntityRenderer
import de.bixilon.minosoft.gui.rendering.events.VisibilityGraphChangeEvent
import de.bixilon.minosoft.modding.event.listener.CallbackEventListener.Companion.listen
import java.util.concurrent.atomic.AtomicInteger
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
class VisibilityManager(val renderer: EntitiesRenderer) {
private var update = false
var size: Int = 0
private set
private val count = AtomicInteger()
val opaque: ArrayList<EntityRenderFeature> = ArrayList(1000)
val translucent: ArrayList<EntityRenderFeature> = ArrayList(1000)
private val lock = SimpleLock()
private val graph = renderer.context.camera.visibilityGraph
private val frustum = renderer.context.camera.matrixHandler.frustum
private var renderDistance = 0
fun init() {
renderer.connection.events.listen<VisibilityGraphChangeEvent> { update = true }
renderer.connection.events.listen<ViewDistanceChangeEvent> { updateViewDistance(server = it.viewDistance) }
renderer.profile.general::renderDistance.observe(this, true) { updateViewDistance(entity = it) }
}
private fun updateViewDistance(entity: Int = renderer.profile.general.renderDistance, server: Int = renderer.connection.world.view.serverViewDistance) {
var distance = if (entity < 0) (server - 1) else entity
distance *= ProtocolDefinition.SECTION_LENGTH
this.renderDistance = distance * distance // length^2
}
fun reset() {
opaque.clear()
translucent.clear()
count.set(0)
size = 0
}
fun update(renderer: EntityRenderer<*>) {
// TODO: check render distance (and maybe entity distance)
private fun EntityRenderer<*>.isInRenderDistance(): Boolean {
return renderDistance < 0 || distance <= renderDistance
}
fun update(renderer: EntityRenderer<*>, millis: Long) {
if (!renderer.isInRenderDistance()) {
// distance is only updated if the renderer is visible, so force update
renderer.updateRenderInfo(millis)
}
if (!renderer.isInRenderDistance()) {
return renderer.updateVisibility(true, true)
}
val aabb = renderer.entity.renderInfo.cameraAABB
val visible = aabb in frustum
if (!visible) {
@ -57,8 +78,8 @@ class VisibilityManager(val renderer: EntitiesRenderer) {
fun collect(renderer: EntityRenderer<*>) {
if (!renderer.visible) return
count.incrementAndGet()
lock.lock()
size++
for (feature in renderer.features) {
if (!feature.enabled || !feature.visible) continue
feature.collect(this)
@ -71,7 +92,6 @@ class VisibilityManager(val renderer: EntitiesRenderer) {
this.opaque.sort()
this.translucent.sort()
this.update = false
size = count.get()
}
operator fun get(layer: EntityLayer) = when (layer) {