diff --git a/build.gradle.kts b/build.gradle.kts index 4c6b7bd1f..8d1c526dc 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -52,6 +52,8 @@ val kutilVersion = getProperty("kutil.version") val os = properties["platform"]?.let { OSTypes[it] } ?: PlatformInfo.OS val architecture = properties["architecture"]?.let { Architectures[it] } ?: PlatformInfo.ARCHITECTURE +logger.info("Building for ${os.name.lowercase()}, ${architecture.name.lowercase()}") + repositories { mavenCentral() maven("https://oss.sonatype.org/content/repositories/snapshots") diff --git a/src/integration-test/kotlin/de/bixilon/minosoft/camera/target/TargetHandlerTest.kt b/src/integration-test/kotlin/de/bixilon/minosoft/camera/target/TargetHandlerTest.kt index 48313c1e3..32679918e 100644 --- a/src/integration-test/kotlin/de/bixilon/minosoft/camera/target/TargetHandlerTest.kt +++ b/src/integration-test/kotlin/de/bixilon/minosoft/camera/target/TargetHandlerTest.kt @@ -13,7 +13,6 @@ package de.bixilon.minosoft.camera.target -import de.bixilon.kotlinglm.vec3.Vec3 import de.bixilon.kotlinglm.vec3.Vec3d import de.bixilon.kotlinglm.vec3.Vec3i import de.bixilon.kutil.observer.DataObserver @@ -24,7 +23,6 @@ import de.bixilon.minosoft.data.entities.EntityRotation import de.bixilon.minosoft.data.physics.PhysicsTestUtil.createPlayer import de.bixilon.minosoft.data.registries.blocks.DirtTest0 import de.bixilon.minosoft.data.registries.blocks.types.stone.StoneTest0 -import de.bixilon.minosoft.gui.rendering.util.VecUtil.toVec3 import de.bixilon.minosoft.protocol.network.connection.play.ConnectionTestUtil.createConnection import org.testng.Assert.* import org.testng.annotations.Test @@ -44,7 +42,7 @@ class TargetHandlerTest { connection.world[7, 69, 6] = DirtTest0.state connection.world[8, 69, 6] = StoneTest0.state - player.renderInfo::eyePosition.forceSet(player.physics.position.toVec3 + Vec3(0.0, 1.5, 0.0)) + player.renderInfo::eyePosition.forceSet(player.physics.position + Vec3d(0.0, 1.5, 0.0)) player.renderInfo::rotation.forceSet(player.physics.rotation) connection.camera.target.update() @@ -68,7 +66,7 @@ class TargetHandlerTest { connection.world[8, 70, 2] = StoneTest0.state - player.renderInfo::eyePosition.forceSet(player.physics.position.toVec3 + Vec3(0.0, 1.5, 0.0)) + player.renderInfo::eyePosition.forceSet(player.physics.position + Vec3d(0.0, 1.5, 0.0)) player.renderInfo::rotation.forceSet(player.physics.rotation) connection.camera.target.update() @@ -92,7 +90,7 @@ class TargetHandlerTest { connection.world[9, 70, 2] = StoneTest0.state - player.renderInfo::eyePosition.forceSet(player.physics.position.toVec3 + Vec3(0.0, 1.5, 0.0)) + player.renderInfo::eyePosition.forceSet(player.physics.position + Vec3d(0.0, 1.5, 0.0)) player.renderInfo::rotation.forceSet(player.physics.rotation) connection.camera.target.update() diff --git a/src/main/java/de/bixilon/minosoft/data/entities/EntityRenderInfo.kt b/src/main/java/de/bixilon/minosoft/data/entities/EntityRenderInfo.kt index be8640a86..852ba9672 100644 --- a/src/main/java/de/bixilon/minosoft/data/entities/EntityRenderInfo.kt +++ b/src/main/java/de/bixilon/minosoft/data/entities/EntityRenderInfo.kt @@ -13,23 +13,23 @@ package de.bixilon.minosoft.data.entities -import de.bixilon.kotlinglm.vec3.Vec3 +import de.bixilon.kotlinglm.vec3.Vec3d import de.bixilon.kutil.math.interpolation.FloatInterpolation.interpolateLinear import de.bixilon.minosoft.data.Tickable import de.bixilon.minosoft.data.entities.entities.Entity import de.bixilon.minosoft.data.registries.shapes.aabb.AABB import de.bixilon.minosoft.gui.rendering.renderer.drawable.Drawable -import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util -import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.blockPosition +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3dUtil +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3dUtil.blockPosition import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition class EntityRenderInfo(private val entity: Entity) : Drawable, Tickable { - private var position0 = Vec3(entity.physics.position) + private var position0 = Vec3d(entity.physics.position) private var position1 = position0 - var position: Vec3 = position0 + var position: Vec3d = position0 private set - var eyePosition: Vec3 = position + var eyePosition: Vec3d = position private set var cameraAABB: AABB = AABB.EMPTY private set @@ -44,8 +44,8 @@ class EntityRenderInfo(private val entity: Entity) : Drawable, Tickable { private fun interpolatePosition(delta: Float) { // TODO: Only interpolate if changed - position = Vec3Util.interpolateLinear(delta, position0, position1) - eyePosition = position + Vec3(0.0f, entity.eyeHeight, 0.0f) + position = Vec3dUtil.interpolateLinear(delta.toDouble(), position0, position1) + eyePosition = position + Vec3d(0.0, entity.eyeHeight, 0.0) cameraAABB = entity.defaultAABB + position eyeBlockPosition = position1.blockPosition } @@ -62,7 +62,7 @@ class EntityRenderInfo(private val entity: Entity) : Drawable, Tickable { override fun tick() { position0 = position1 - position1 = Vec3(entity.physics.position) + position1 = Vec3d(entity.physics.position) rotation0 = rotation1 rotation1 = entity.physics.rotation diff --git a/src/main/java/de/bixilon/minosoft/data/world/World.kt b/src/main/java/de/bixilon/minosoft/data/world/World.kt index f6384f338..8e16a1231 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/World.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/World.kt @@ -239,7 +239,7 @@ class World( } companion object { - const val MAX_SIZE = 29999999 + const val MAX_SIZE = 30_000_000 const val MAX_SIZEf = MAX_SIZE.toFloat() const val MAX_SIZEd = MAX_SIZE.toDouble() const val MAX_RENDER_DISTANCE = 64 diff --git a/src/main/java/de/bixilon/minosoft/data/world/audio/AbstractAudioPlayer.kt b/src/main/java/de/bixilon/minosoft/data/world/audio/AbstractAudioPlayer.kt index c164467a4..a2073cbf5 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/audio/AbstractAudioPlayer.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/audio/AbstractAudioPlayer.kt @@ -13,21 +13,21 @@ package de.bixilon.minosoft.data.world.audio -import de.bixilon.kotlinglm.vec3.Vec3 +import de.bixilon.kotlinglm.vec3.Vec3d import de.bixilon.kotlinglm.vec3.Vec3i import de.bixilon.minosoft.data.registries.identified.ResourceLocation -import de.bixilon.minosoft.gui.rendering.util.VecUtil.centerf +import de.bixilon.minosoft.gui.rendering.util.VecUtil.center interface AbstractAudioPlayer { fun playSoundEvent(sound: ResourceLocation, position: Vec3i? = null, volume: Float = 1.0f, pitch: Float = 1.0f) { - playSound(sound, position?.centerf, volume, pitch) + playSound(sound, position?.center, volume, pitch) } - fun playSound(sound: ResourceLocation, position: Vec3? = null, volume: Float = 1.0f, pitch: Float = 1.0f) + fun playSound(sound: ResourceLocation, position: Vec3d? = null, volume: Float = 1.0f, pitch: Float = 1.0f) fun play2DSound(sound: ResourceLocation, volume: Float = 1.0f, pitch: Float = 1.0f) { - playSound(sound, null as Vec3?, volume, pitch) + playSound(sound, null as Vec3d?, volume, pitch) } fun stopAllSounds() diff --git a/src/main/java/de/bixilon/minosoft/data/world/audio/WorldAudioPlayer.kt b/src/main/java/de/bixilon/minosoft/data/world/audio/WorldAudioPlayer.kt index 3cd49f834..0d4d093cd 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/audio/WorldAudioPlayer.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/audio/WorldAudioPlayer.kt @@ -13,14 +13,14 @@ package de.bixilon.minosoft.data.world.audio -import de.bixilon.kotlinglm.vec3.Vec3 +import de.bixilon.kotlinglm.vec3.Vec3d import de.bixilon.minosoft.data.registries.identified.ResourceLocation @Deprecated("") interface WorldAudioPlayer : AbstractAudioPlayer { val audioPlayer: AbstractAudioPlayer? - override fun playSound(sound: ResourceLocation, position: Vec3?, volume: Float, pitch: Float) { + override fun playSound(sound: ResourceLocation, position: Vec3d?, volume: Float, pitch: Float) { audioPlayer?.playSound(sound, position, volume, pitch) } diff --git a/src/main/java/de/bixilon/minosoft/data/world/border/WorldBorder.kt b/src/main/java/de/bixilon/minosoft/data/world/border/WorldBorder.kt index 15830ac0c..dc94f97b5 100644 --- a/src/main/java/de/bixilon/minosoft/data/world/border/WorldBorder.kt +++ b/src/main/java/de/bixilon/minosoft/data/world/border/WorldBorder.kt @@ -14,57 +14,42 @@ package de.bixilon.minosoft.data.world.border import de.bixilon.kotlinglm.vec2.Vec2d -import de.bixilon.kotlinglm.vec3.Vec3 import de.bixilon.kotlinglm.vec3.Vec3d import de.bixilon.kotlinglm.vec3.Vec3i -import de.bixilon.kutil.concurrent.lock.simple.SimpleLock -import de.bixilon.kutil.math.interpolation.DoubleInterpolation.interpolateLinear -import de.bixilon.kutil.time.TimeUtil -import de.bixilon.kutil.time.TimeUtil.millis import de.bixilon.minosoft.data.world.World +import de.bixilon.minosoft.data.world.border.area.BorderArea +import de.bixilon.minosoft.data.world.border.area.DynamicBorderArea +import de.bixilon.minosoft.data.world.border.area.StaticBorderArea import de.bixilon.minosoft.data.world.positions.BlockPosition import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2dUtil.EMPTY +import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition import kotlin.math.abs class WorldBorder { var center = Vec2d.EMPTY - var diameter = DEFAULT_DIAMETER var warningTime = 0 var warningBlocks = 0 var portalBound = 0 - var state = WorldBorderState.STATIC - private set - - private var interpolationStart = -1L - private var interpolationEnd = -1L - private var oldDiameter = DEFAULT_DIAMETER - private var newDiameter = DEFAULT_DIAMETER - - val lock = SimpleLock() + var area: BorderArea = StaticBorderArea(MAX_RADIUS) fun isOutside(blockPosition: Vec3i): Boolean { return isOutside(blockPosition.x.toDouble(), blockPosition.z.toDouble()) && isOutside(blockPosition.x + 1.0, blockPosition.z + 1.0) } - fun isOutside(position: Vec3): Boolean { - return isOutside(position.x.toDouble(), position.z.toDouble()) - } - fun isOutside(position: Vec3d): Boolean { return isOutside(position.x, position.z) } fun isOutside(x: Double, z: Double): Boolean { - lock.acquire() - val radius = diameter / 2 - val inside = x in (center.x - radius)..(radius + center.x) && z in (center.y - radius)..(radius + center.y) - lock.release() + val center = center + val radius = area.radius + val inside = x in maxOf(-MAX_RADIUS, center.x - radius)..minOf(MAX_RADIUS, center.x + radius) && z in maxOf(-MAX_RADIUS, center.y - radius)..minOf(MAX_RADIUS, center.y + radius) return !inside } - operator fun contains(position:BlockPosition) = !isOutside(position) + operator fun contains(position: BlockPosition) = !isOutside(position) operator fun contains(position: Vec3d) = !isOutside(position) @@ -73,76 +58,32 @@ class WorldBorder { } fun getDistanceTo(x: Double, z: Double): Double { - lock.acquire() - val radius = diameter / 2 + val center = center + val radius = area.radius - val closestDistance = minOf( - radius - abs(x) - abs(center.x), - radius - abs(z) - abs(center.y), + return minOf( + minOf(MAX_RADIUS, radius - abs(center.x)) - abs(x), + minOf(MAX_RADIUS, radius - abs(center.y)) - abs(z), ) - lock.release() - return closestDistance } - fun stopInterpolating() { - lock.lock() - interpolationStart = -1L - lock.unlock() - } - - fun interpolate(oldDiameter: Double, newDiameter: Double, millis: Long) { - if (millis == 0L) { - stopInterpolating() - diameter = newDiameter + fun interpolate(oldRadius: Double, newRadius: Double, millis: Long) { + if (millis <= 0L || oldRadius == newRadius) { + area = StaticBorderArea(newRadius) + return } - lock.lock() - val time = millis() - interpolationStart = time - interpolationEnd = time + millis - this.oldDiameter = oldDiameter - this.newDiameter = newDiameter - lock.unlock() + area = DynamicBorderArea(this, oldRadius, newRadius, millis) } fun tick() { - lock.lock() - if (interpolationStart < 0L) { - lock.unlock() - return - } - val time = millis() - if (interpolationEnd <= time) { - state = WorldBorderState.STATIC - interpolationStart = -1L - lock.unlock() - return - } - val oldDiameter = diameter - - val remaining = interpolationEnd - time - val totalTime = (interpolationEnd - interpolationStart) - val diameter = interpolateLinear(remaining.toDouble() / totalTime.toDouble(), this.newDiameter, this.oldDiameter) - this.diameter = diameter - - state = if (oldDiameter > diameter) { - WorldBorderState.SHRINKING - } else if (oldDiameter < diameter) { - WorldBorderState.GROWING - } else { - interpolationStart = -1L - WorldBorderState.STATIC - } - lock.unlock() + area.tick() } fun reset() { - lock.lock() - diameter = DEFAULT_DIAMETER - interpolationStart = -1L - lock.unlock() + area = StaticBorderArea(MAX_RADIUS) } companion object { - const val DEFAULT_DIAMETER = World.MAX_SIZE.toDouble() * 2 + const val MAX_RADIUS = (World.MAX_SIZE - ProtocolDefinition.SECTION_WIDTH_X).toDouble() } } diff --git a/src/main/java/de/bixilon/minosoft/data/world/border/area/BorderArea.kt b/src/main/java/de/bixilon/minosoft/data/world/border/area/BorderArea.kt new file mode 100644 index 000000000..c7e692ae4 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/data/world/border/area/BorderArea.kt @@ -0,0 +1,27 @@ +/* + * 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 . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.data.world.border.area + +import de.bixilon.kutil.time.TimeUtil.millis +import de.bixilon.minosoft.data.Tickable +import de.bixilon.minosoft.data.world.border.WorldBorderState + +interface BorderArea : Tickable { + val radius: Double + + val state: WorldBorderState + + + fun radius(time: Long = millis()): Double = radius +} diff --git a/src/main/java/de/bixilon/minosoft/data/world/border/area/DynamicBorderArea.kt b/src/main/java/de/bixilon/minosoft/data/world/border/area/DynamicBorderArea.kt new file mode 100644 index 000000000..c34c07000 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/data/world/border/area/DynamicBorderArea.kt @@ -0,0 +1,57 @@ +/* + * 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 . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.data.world.border.area + +import de.bixilon.kutil.math.interpolation.DoubleInterpolation.interpolateLinear +import de.bixilon.kutil.time.TimeUtil.millis +import de.bixilon.minosoft.data.world.border.WorldBorder +import de.bixilon.minosoft.data.world.border.WorldBorderState + +class DynamicBorderArea( + val border: WorldBorder, + val oldRadius: Double, + val newRadius: Double, + val millis: Long, +) : BorderArea { + val start: Long = millis() + val end = start + millis + + override var state: WorldBorderState = state() + override var radius: Double = oldRadius + + override fun radius(time: Long): Double { + return interpolateLinear(progress(time), oldRadius, newRadius) + } + + private fun progress(time: Long): Double { + return (time - start).toDouble() / (end - start) + } + + override fun tick() { + val time = millis() + if (end <= time) { + border.area = StaticBorderArea(newRadius) + return + } + + this.radius = interpolateLinear(progress(time), this.oldRadius, this.newRadius) + this.state = state() + } + + private fun state() = when { + oldRadius > newRadius -> WorldBorderState.SHRINKING + oldRadius < newRadius -> WorldBorderState.GROWING + else -> WorldBorderState.STATIC // impossible? + } +} diff --git a/src/main/java/de/bixilon/minosoft/data/world/border/area/StaticBorderArea.kt b/src/main/java/de/bixilon/minosoft/data/world/border/area/StaticBorderArea.kt new file mode 100644 index 000000000..8f904cd90 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/data/world/border/area/StaticBorderArea.kt @@ -0,0 +1,24 @@ +/* + * 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 . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.data.world.border.area + +import de.bixilon.minosoft.data.world.border.WorldBorderState + +class StaticBorderArea( + override val radius: Double, +) : BorderArea { + override val state: WorldBorderState get() = WorldBorderState.STATIC + + override fun tick() = Unit +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/camera/Camera.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/Camera.kt index 346fa5ac6..66100a1fb 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/camera/Camera.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/Camera.kt @@ -31,6 +31,7 @@ class Camera( val view = ViewManager(this) + val offset = WorldOffset(this) fun init() { matrixHandler.init() diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/camera/MatrixHandler.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/MatrixHandler.kt index 7cf128de4..04f23479b 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/camera/MatrixHandler.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/MatrixHandler.kt @@ -32,7 +32,7 @@ import de.bixilon.minosoft.gui.rendering.events.ResizeWindowEvent import de.bixilon.minosoft.gui.rendering.shader.types.CameraPositionShader import de.bixilon.minosoft.gui.rendering.shader.types.ViewProjectionShader import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY -import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.blockPosition +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3dUtil.blockPosition import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.chunkPosition import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.sectionHeight import de.bixilon.minosoft.modding.event.listener.CallbackEventListener.Companion.listen @@ -45,9 +45,9 @@ class MatrixHandler( private val connection = context.connection private val profile = context.connection.profiles.rendering.camera val shaking = CameraShaking(camera, profile.shaking) - val frustum = Frustum(this, connection.world) + val frustum = Frustum(camera, this, connection.world) - private var eyePosition = Vec3.EMPTY + private var matrixPosition = Vec3.EMPTY private var previousFOV = 0.0f private var front = Vec3.EMPTY @@ -113,11 +113,13 @@ class MatrixHandler( val fov = calculateFOV() val view = camera.view.view val eyePosition = view.eyePosition + context.camera.offset.draw() + val matrixPosition = Vec3(eyePosition - context.camera.offset.offset) val front = view.front - if (upToDate && eyePosition == this.eyePosition && front == this.front && fov == previousFOV && shaking.isEmpty) { + if (upToDate && matrixPosition == this.matrixPosition && front == this.front && fov == previousFOV && shaking.isEmpty) { return } - this.eyePosition = eyePosition + this.matrixPosition = matrixPosition this.front = front val cameraBlockPosition = eyePosition.blockPosition if (fov != previousFOV) { @@ -126,17 +128,18 @@ class MatrixHandler( previousFOV = fov updateFront(front) - updateViewMatrix(eyePosition, front) + updateViewMatrix(matrixPosition, front) updateViewProjectionMatrix() - val usePosition = if (view.updateFrustum) eyePosition else connection.camera.entity.renderInfo.eyePosition + val useMatrixPosition = if (view.updateFrustum) matrixPosition else Vec3(connection.camera.entity.renderInfo.eyePosition - camera.offset.offset) + val useEyePosition = if (view.updateFrustum) eyePosition else connection.camera.entity.renderInfo.eyePosition if (view.updateFrustum) { frustum.recalculate() camera.visibilityGraph.updateCamera(cameraBlockPosition.chunkPosition, cameraBlockPosition.sectionHeight) } - connection.events.fire(CameraPositionChangeEvent(context, usePosition)) + connection.events.fire(CameraPositionChangeEvent(context, useEyePosition)) connection.events.fire( CameraMatrixChangeEvent( @@ -147,7 +150,7 @@ class MatrixHandler( ) ) - updateShaders(usePosition) + updateShaders(useMatrixPosition) upToDate = true } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/camera/WorldOffset.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/WorldOffset.kt new file mode 100644 index 000000000..5cd8c7547 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/WorldOffset.kt @@ -0,0 +1,48 @@ +/* + * 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 . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.camera + +import de.bixilon.kotlinglm.vec3.Vec3i +import de.bixilon.kutil.observer.DataObserver.Companion.observed +import de.bixilon.minosoft.data.world.World +import de.bixilon.minosoft.gui.rendering.renderer.drawable.Drawable +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3dUtil.blockPosition +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.EMPTY +import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition + +class WorldOffset(private val camera: Camera) : Drawable { + var offset by observed(Vec3i.EMPTY) + private set + + override fun draw() { + val blockPosition = camera.view.view.eyePosition.blockPosition + + val previous = offset / MAX_DISTANCE + val maxOffset = (blockPosition + THRESHOLD) / MAX_DISTANCE + val minOffset = (blockPosition - THRESHOLD) / MAX_DISTANCE + if (maxOffset == previous || minOffset == previous) { + // we need to get away further + // this makes the "border" not just 1 pixel wide, it is 256 blocks wide + return + } + this.offset = (blockPosition / MAX_DISTANCE) * MAX_DISTANCE + // Log.log(LogMessageType.OTHER, LogLevels.VERBOSE) { "Offset changed: $offset" } + } + + + companion object { + const val MAX_DISTANCE = World.MAX_RENDER_DISTANCE * ProtocolDefinition.SECTION_WIDTH_X // coordinates higher than that value are not allowed + const val THRESHOLD = (World.MAX_RENDER_DISTANCE / 8) * ProtocolDefinition.SECTION_WIDTH_X // only if value is lower that that value coordinates will be back offset + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/camera/frustum/Frustum.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/frustum/Frustum.kt index eb3a8dcb7..3e2116006 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/camera/frustum/Frustum.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/frustum/Frustum.kt @@ -25,6 +25,7 @@ import de.bixilon.kutil.enums.ValuesEnum import de.bixilon.minosoft.data.registries.shapes.aabb.AABB import de.bixilon.minosoft.data.world.World import de.bixilon.minosoft.gui.rendering.RenderConstants +import de.bixilon.minosoft.gui.rendering.camera.Camera import de.bixilon.minosoft.gui.rendering.camera.MatrixHandler import de.bixilon.minosoft.gui.rendering.util.VecUtil.of import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.EMPTY @@ -33,6 +34,7 @@ import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition // Big thanks to: https://gist.github.com/podgorskiy/e698d18879588ada9014768e3e82a644 class Frustum( + private val camera: Camera, private val matrixHandler: MatrixHandler, private val world: World, ) { @@ -152,7 +154,8 @@ class Frustum( } fun containsChunkSection(chunkPosition: Vec2i, sectionHeight: Int, minPosition: Vec3i = CHUNK_NIN_POSITION, maxPosition: Vec3i = ProtocolDefinition.CHUNK_SECTION_SIZE): Boolean { - val base = Vec3i.of(chunkPosition, sectionHeight) + val offset = camera.offset.offset + val base = Vec3i.of(chunkPosition, sectionHeight) - offset val min = base + minPosition val max = base + maxPosition + 1 return containsRegion(Vec3(min), Vec3(max)) @@ -160,18 +163,21 @@ class Frustum( fun containsChunk(chunkPosition: Vec2i): Boolean { val dimension = world.dimension - val minY = dimension.minY - val maxY = dimension.maxY - val base = Vec2i(chunkPosition.x * ProtocolDefinition.SECTION_WIDTH_X, chunkPosition.y * ProtocolDefinition.SECTION_WIDTH_Z) + val offset = camera.offset.offset + val minY = dimension.minY - offset.y + val maxY = dimension.maxY - offset.y + val base = Vec2i(chunkPosition.x * ProtocolDefinition.SECTION_WIDTH_X - offset.x, chunkPosition.y * ProtocolDefinition.SECTION_WIDTH_Z - offset.z) return containsRegion(Vec3(base.x, minY, base.y), Vec3(base.x + ProtocolDefinition.SECTION_WIDTH_X, maxY, base.y + ProtocolDefinition.SECTION_WIDTH_Z)) } fun containsRegion(min: Vec3i, max: Vec3i): Boolean { - return containsRegion(Vec3(min), Vec3(max)) + val offset = camera.offset.offset + return containsRegion(Vec3(min - offset), Vec3(max - offset)) } fun containsAABB(aabb: AABB): Boolean { - return containsRegion(Vec3(aabb.min), Vec3(aabb.max)) + val offset = camera.offset.offset + return containsRegion(Vec3(aabb.min - offset), Vec3(aabb.max - offset)) } private data class FrustumData(val normals: Array, val planes: Array) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/camera/view/CameraView.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/view/CameraView.kt index 228aab6e4..5e3371634 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/camera/view/CameraView.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/view/CameraView.kt @@ -15,6 +15,7 @@ package de.bixilon.minosoft.gui.rendering.camera.view import de.bixilon.kotlinglm.vec2.Vec2d import de.bixilon.kotlinglm.vec3.Vec3 +import de.bixilon.kotlinglm.vec3.Vec3d import de.bixilon.minosoft.data.entities.EntityRotation import de.bixilon.minosoft.gui.rendering.RenderContext import de.bixilon.minosoft.input.camera.MovementInputActions @@ -30,7 +31,7 @@ interface CameraView { val updateFrustum: Boolean get() = true - val eyePosition: Vec3 + val eyePosition: Vec3d val rotation: EntityRotation val front: Vec3 diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/camera/view/DebugView.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/view/DebugView.kt index b99775863..881f5f5ab 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/camera/view/DebugView.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/view/DebugView.kt @@ -15,11 +15,13 @@ package de.bixilon.minosoft.gui.rendering.camera.view import de.bixilon.kotlinglm.vec2.Vec2d import de.bixilon.kotlinglm.vec3.Vec3 +import de.bixilon.kotlinglm.vec3.Vec3d import de.bixilon.minosoft.data.entities.EntityRotation import de.bixilon.minosoft.gui.rendering.RenderContext import de.bixilon.minosoft.gui.rendering.camera.Camera import de.bixilon.minosoft.gui.rendering.camera.CameraDefinition.CAMERA_UP_VEC3 import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3dUtil.EMPTY import de.bixilon.minosoft.input.camera.MovementInputActions import de.bixilon.minosoft.input.camera.PlayerMovementInput @@ -28,7 +30,7 @@ class DebugView(private val camera: Camera) : CameraView { override val updateFrustum: Boolean get() = false override val shaking: Boolean get() = false - override var eyePosition = Vec3.EMPTY + override var eyePosition = Vec3d.EMPTY override var rotation = EntityRotation.EMPTY override var front = Vec3.EMPTY @@ -44,7 +46,7 @@ class DebugView(private val camera: Camera) : CameraView { speedMultiplier *= 2 } - val movement = Vec3.EMPTY + val movement = Vec3d.EMPTY if (input.forwards != 0.0f) { movement += front * input.forwards @@ -54,7 +56,7 @@ class DebugView(private val camera: Camera) : CameraView { movement += cameraRight * input.sideways } - if (movement.length2() != 0.0f) { + if (movement.length2() != 0.0) { movement.normalizeAssign() } movement *= speedMultiplier @@ -73,7 +75,7 @@ class DebugView(private val camera: Camera) : CameraView { } override fun onAttach(previous: CameraView?) { - this.eyePosition = previous?.eyePosition ?: Vec3.EMPTY + this.eyePosition = previous?.eyePosition ?: Vec3d.EMPTY this.rotation = previous?.rotation ?: EntityRotation.EMPTY this.front = previous?.front ?: Vec3.EMPTY } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/camera/view/person/FirstPersonView.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/view/person/FirstPersonView.kt index 4e6825a0d..ce29e5eb9 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/camera/view/person/FirstPersonView.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/view/person/FirstPersonView.kt @@ -15,6 +15,7 @@ package de.bixilon.minosoft.gui.rendering.camera.view.person import de.bixilon.kotlinglm.vec2.Vec2d import de.bixilon.kotlinglm.vec3.Vec3 +import de.bixilon.kotlinglm.vec3.Vec3d import de.bixilon.minosoft.data.abilities.Gamemodes import de.bixilon.minosoft.data.entities.EntityRotation import de.bixilon.minosoft.data.entities.entities.player.PlayerEntity @@ -22,6 +23,7 @@ import de.bixilon.minosoft.gui.rendering.RenderContext import de.bixilon.minosoft.gui.rendering.camera.Camera import de.bixilon.minosoft.gui.rendering.camera.view.CameraView import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3dUtil.EMPTY class FirstPersonView(override val camera: Camera) : PersonView { override val context: RenderContext get() = camera.context @@ -37,7 +39,7 @@ class FirstPersonView(override val camera: Camera) : PersonView { } override val renderOverlays: Boolean get() = true - override var eyePosition: Vec3 = Vec3.EMPTY + override var eyePosition: Vec3d = Vec3d.EMPTY override var rotation = EntityRotation.EMPTY override var front = Vec3.EMPTY diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/camera/view/person/ThirdPersonView.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/view/person/ThirdPersonView.kt index 7b1d04099..804fcb585 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/camera/view/person/ThirdPersonView.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/view/person/ThirdPersonView.kt @@ -15,12 +15,14 @@ package de.bixilon.minosoft.gui.rendering.camera.view.person import de.bixilon.kotlinglm.vec2.Vec2d import de.bixilon.kotlinglm.vec3.Vec3 +import de.bixilon.kotlinglm.vec3.Vec3d import de.bixilon.minosoft.data.entities.EntityRotation import de.bixilon.minosoft.gui.rendering.RenderContext import de.bixilon.minosoft.gui.rendering.camera.Camera import de.bixilon.minosoft.gui.rendering.camera.view.CameraView import de.bixilon.minosoft.gui.rendering.util.VecUtil.toVec3d import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3dUtil.EMPTY import de.bixilon.minosoft.input.camera.MovementInputActions import de.bixilon.minosoft.input.camera.PlayerMovementInput @@ -28,7 +30,7 @@ import de.bixilon.minosoft.input.camera.PlayerMovementInput class ThirdPersonView(override val camera: Camera) : PersonView { override val context: RenderContext get() = camera.context - override var eyePosition: Vec3 = Vec3.EMPTY + override var eyePosition: Vec3d = Vec3d.EMPTY override var rotation = EntityRotation.EMPTY override var front = Vec3.EMPTY @@ -53,8 +55,8 @@ class ThirdPersonView(override val camera: Camera) : PersonView { update(entity.renderInfo.eyePosition, front) } - private fun update(position: Vec3, front: Vec3) { - val target = camera.context.connection.camera.target.raycastBlock(position.toVec3d, (-front).toVec3d).first + private fun update(position: Vec3d, front: Vec3) { + val target = camera.context.connection.camera.target.raycastBlock(position, (-front).toVec3d).first val distance = target?.distance?.let { minOf(it, MAX_DISTANCE) } ?: MAX_DISTANCE this.eyePosition = position + (-front * distance) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entity/EntityRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entity/EntityRenderer.kt index 7069f8432..03735da0c 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entity/EntityRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entity/EntityRenderer.kt @@ -61,6 +61,8 @@ class EntityRenderer( var visibleCount: Int = 0 private set + private var reset = false + override fun init(latch: CountUpAndDownLatch) { connection.events.listen { event -> if (event.entity is LocalPlayerEntity) return@listen @@ -75,6 +77,7 @@ class EntityRenderer( } profile.hitbox::enabled.observe(this) { this.hitboxes = it } + context.camera.offset::offset.observe(this) { reset = true } context.inputHandler.registerKeyCallback( HITBOX_TOGGLE_KEY_COMBINATION, @@ -104,8 +107,12 @@ class EntityRenderer( override fun prePrepareDraw() { val count = AtomicInteger() + val reset = reset runAsync { it.entity.draw(millis()) + if (reset) { + it.reset() + } it.update = it.checkUpdate() it.prepareAsync() if (it.visible) { @@ -113,6 +120,9 @@ class EntityRenderer( } } this.visibleCount = count.get() + if (reset) { + this.reset = false + } } override fun postPrepareDraw() { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entity/ModelUpdater.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entity/ModelUpdater.kt index eafeb15e7..44b66bab0 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entity/ModelUpdater.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entity/ModelUpdater.kt @@ -23,4 +23,6 @@ interface ModelUpdater : Drawable { fun prepare() = Unit fun unload() = Unit + + fun reset() = Unit } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entity/hitbox/EntityHitbox.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entity/hitbox/EntityHitbox.kt index 77ff044be..6f17896a2 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entity/hitbox/EntityHitbox.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entity/hitbox/EntityHitbox.kt @@ -14,6 +14,7 @@ package de.bixilon.minosoft.gui.rendering.entity.hitbox import de.bixilon.kotlinglm.vec3.Vec3 +import de.bixilon.kotlinglm.vec3.Vec3d import de.bixilon.minosoft.data.entities.entities.LivingEntity import de.bixilon.minosoft.data.registries.shapes.aabb.AABB import de.bixilon.minosoft.data.text.formatting.color.ChatColors @@ -31,7 +32,6 @@ class EntityHitbox( private var aabb: AABB = model.aabb private var data: HitboxData? = null - private var update = true var enabled: Boolean = true get() = field && model.renderer.hitboxes @@ -52,7 +52,6 @@ class EntityHitbox( } this.data = data this.aabb = aabb - update = true return true } @@ -80,18 +79,21 @@ class EntityHitbox( } else { mesh.drawAABB(aabb = shrunk, color = data.color, margin = 0.1f) } - val center = Vec3(shrunk.center) + val offset = model.context.camera.offset.offset + val center = Vec3(shrunk.center - offset) + + data.velocity?.let { mesh.drawLine(center, center + Vec3(it) * 3, color = ChatColors.YELLOW) } val eyeHeight = shrunk.min.y + model.entity.eyeHeight - val eyeAABB = AABB(Vec3(shrunk.min.x, eyeHeight, shrunk.min.z), Vec3(shrunk.max.x, eyeHeight, shrunk.max.z)).hShrink(RenderConstants.DEFAULT_LINE_WIDTH) + val eyeAABB = AABB(Vec3d(shrunk.min.x, eyeHeight, shrunk.min.z), Vec3d(shrunk.max.x, eyeHeight, shrunk.max.z)).hShrink(-RenderConstants.DEFAULT_LINE_WIDTH) mesh.drawAABB(eyeAABB, RenderConstants.DEFAULT_LINE_WIDTH, ChatColors.DARK_RED) - val eyeStart = Vec3(center.x, eyeHeight, center.z) + val eyeStart = Vec3(center.x, eyeHeight - offset.y, center.z) - mesh.drawLine(eyeStart, eyeStart + Vec3(data.rotation.front) * 5.0f, color = ChatColors.BLUE) + mesh.drawLine(eyeStart, eyeStart + data.rotation.front * 5.0f, color = ChatColors.BLUE) this.mesh = mesh } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entity/models/EntityModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entity/models/EntityModel.kt index f99ba27b5..74711a38e 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entity/models/EntityModel.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entity/models/EntityModel.kt @@ -47,6 +47,11 @@ abstract class EntityModel( return update } + override fun reset() { + update = true + hitbox.reset() + } + override fun prepareAsync() { if (!update) { return diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/events/CameraPositionChangeEvent.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/events/CameraPositionChangeEvent.kt index 75e1dcea6..8e339c532 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/events/CameraPositionChangeEvent.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/events/CameraPositionChangeEvent.kt @@ -13,13 +13,13 @@ package de.bixilon.minosoft.gui.rendering.events -import de.bixilon.kotlinglm.vec3.Vec3 +import de.bixilon.kotlinglm.vec3.Vec3d import de.bixilon.minosoft.gui.rendering.RenderContext class CameraPositionChangeEvent( context: RenderContext, - newPosition: Vec3, + newPosition: Vec3d, ) : RenderEvent(context) { - val newPosition: Vec3 = newPosition - get() = Vec3(field) + val newPosition: Vec3d = newPosition + get() = Vec3d(field) } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/exceptions/ShaderLoadingException.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/exceptions/ShaderLoadingException.kt index cb6511332..062170b29 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/exceptions/ShaderLoadingException.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/exceptions/ShaderLoadingException.kt @@ -12,7 +12,10 @@ */ package de.bixilon.minosoft.gui.rendering.exceptions +import de.bixilon.minosoft.config.StaticConfiguration + class ShaderLoadingException : Exception { constructor() constructor(message: String) : super(message) + constructor(message: String, code: String) : super(message + if (StaticConfiguration.DEBUG_MODE) "\n\n\n" + code else "") } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/framebuffer/world/overlay/overlays/simple/WallOverlay.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/framebuffer/world/overlay/overlays/simple/WallOverlay.kt index c956ab768..2c426025b 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/framebuffer/world/overlay/overlays/simple/WallOverlay.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/framebuffer/world/overlay/overlays/simple/WallOverlay.kt @@ -26,7 +26,7 @@ import de.bixilon.minosoft.data.world.positions.BlockPositionUtil.positionHash import de.bixilon.minosoft.gui.rendering.RenderContext import de.bixilon.minosoft.gui.rendering.framebuffer.world.overlay.OverlayFactory import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture -import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.blockPosition +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3dUtil.blockPosition import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.EMPTY import java.util.* diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/SingleBlockRenderable.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/SingleBlockRenderable.kt index c9271e1c1..be9c1a23b 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/SingleBlockRenderable.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/SingleBlockRenderable.kt @@ -20,5 +20,5 @@ import java.util.* interface SingleBlockRenderable { - fun singleRender(position: Vec3i, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array, light: ByteArray, tints: IntArray?): Boolean + fun singleRender(position: Vec3i, offset: FloatArray, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array, light: ByteArray, tints: IntArray?): Boolean } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/MultipartBakedModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/MultipartBakedModel.kt index e50d968e9..530b9167a 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/MultipartBakedModel.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/MultipartBakedModel.kt @@ -32,10 +32,10 @@ class MultipartBakedModel( return sizes[direction.ordinal] } - override fun singleRender(position: Vec3i, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array, light: ByteArray, tints: IntArray?): Boolean { + override fun singleRender(position: Vec3i, offset: FloatArray, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array, light: ByteArray, tints: IntArray?): Boolean { var rendered = false for (model in models) { - if (model.singleRender(position, mesh, random, blockState, neighbours, light, tints) && !rendered) { + if (model.singleRender(position, offset, mesh, random, blockState, neighbours, light, tints) && !rendered) { rendered = true } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/WeightedBakedModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/WeightedBakedModel.kt index 58f391683..758508d9c 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/WeightedBakedModel.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/WeightedBakedModel.kt @@ -59,8 +59,8 @@ class WeightedBakedModel( Broken("Could not find a model: This should never happen!") } - override fun singleRender(position: Vec3i, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array, light: ByteArray, tints: IntArray?): Boolean { - return getModel(random)?.singleRender(position, mesh, random, blockState, neighbours, light, tints) ?: false + override fun singleRender(position: Vec3i, offset: FloatArray, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array, light: ByteArray, tints: IntArray?): Boolean { + return getModel(random)?.singleRender(position, offset, mesh, random, blockState, neighbours, light, tints) ?: false } override fun getParticleTexture(random: Random, blockPosition: Vec3i): AbstractTexture? { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/block/BakedBlockStateModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/block/BakedBlockStateModel.kt index 0bdf8fa5d..60c37aeb0 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/block/BakedBlockStateModel.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/models/baked/block/BakedBlockStateModel.kt @@ -25,7 +25,7 @@ import de.bixilon.minosoft.gui.rendering.models.properties.AbstractFacePropertie import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture import de.bixilon.minosoft.gui.rendering.tint.TintManager import de.bixilon.minosoft.gui.rendering.util.VecUtil.getWorldOffset -import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.toVec3 +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.toVec3 import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh import de.bixilon.minosoft.gui.rendering.world.preparer.cull.SolidCullSectionPreparer import java.util.* @@ -40,8 +40,8 @@ class BakedBlockStateModel( return touchingFaceProperties[direction.ordinal] } - override fun singleRender(position: Vec3i, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array, light: ByteArray, tints: IntArray?): Boolean { - val floatPosition = position.toVec3() + override fun singleRender(position: Vec3i, offset: FloatArray, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array, light: ByteArray, tints: IntArray?): Boolean { + val floatPosition = offset.toVec3() if (blockState.block is RandomOffsetBlock) { blockState.block.randomOffset?.let { floatPosition += position.getWorldOffset(it) } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/particle/ParticleMesh.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/particle/ParticleMesh.kt index d87e7bdaa..32a3f3fef 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/particle/ParticleMesh.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/particle/ParticleMesh.kt @@ -35,9 +35,10 @@ class ParticleMesh(context: RenderContext, data: AbstractFloatList) : Mesh(conte } val maxTransformedUV = texture.renderData.transformUV(uvMax) val data = data - data.add(position.x.toFloat()) - data.add(position.y.toFloat()) - data.add(position.z.toFloat()) + val offset = context.camera.offset.offset + data.add((position.x - offset.x).toFloat()) + data.add((position.y - offset.y).toFloat()) + data.add((position.z - offset.z).toFloat()) data.add(minTransformedUV) data.add(maxTransformedUV) data.add(texture.renderData.shaderTextureId.buffer()) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/instance/SkeletalInstance.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/instance/SkeletalInstance.kt index 20145c271..471f6b2cb 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/instance/SkeletalInstance.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/instance/SkeletalInstance.kt @@ -16,6 +16,7 @@ package de.bixilon.minosoft.gui.rendering.skeletal.instance import de.bixilon.kotlinglm.func.rad import de.bixilon.kotlinglm.mat4x4.Mat4 import de.bixilon.kotlinglm.vec3.Vec3 +import de.bixilon.kotlinglm.vec3.Vec3d import de.bixilon.kutil.time.TimeUtil.millis import de.bixilon.minosoft.data.entities.EntityRotation import de.bixilon.minosoft.gui.rendering.RenderContext @@ -71,9 +72,9 @@ class SkeletalInstance( context.skeletalManager.draw(this, light) } - fun updatePosition(position: Vec3, rotation: EntityRotation) { + fun updatePosition(position: Vec3d, rotation: EntityRotation) { val matrix = Mat4() - .translateAssign(position) + .translateAssign(Vec3(position - context.camera.offset.offset)) .rotateAssign((180.0f - rotation.yaw).rad, Vec3(0, 1, 0)) .translateAssign(Vec3(-0.5, 0.0f, -0.5)) // move to bottom center diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/sky/box/SkyboxRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/sky/box/SkyboxRenderer.kt index a2a023227..8aa109cc9 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/sky/box/SkyboxRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/sky/box/SkyboxRenderer.kt @@ -45,8 +45,8 @@ import de.bixilon.minosoft.gui.rendering.events.CameraPositionChangeEvent import de.bixilon.minosoft.gui.rendering.sky.SkyChildRenderer import de.bixilon.minosoft.gui.rendering.sky.SkyRenderer import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture -import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.blockPosition import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.interpolateLinear +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3dUtil.blockPosition import de.bixilon.minosoft.modding.event.listener.CallbackEventListener.Companion.listen import java.util.* import kotlin.math.PI diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/sky/clouds/CloudArray.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/sky/clouds/CloudArray.kt index 48d6cb2f6..9b5a09ff5 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/sky/clouds/CloudArray.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/sky/clouds/CloudArray.kt @@ -27,6 +27,7 @@ class CloudArray( } private fun build() { + val offset = layer.clouds.context.camera.offset.offset val matrix = layer.clouds.matrix val matrixOffset = (offset * ARRAY_SIZE) and 0xFF @@ -47,7 +48,7 @@ class CloudArray( matrix[matrixX - 1, matrixZ + 0], // WEST matrix[matrixX + 1, matrixZ + 0], // EAST ) - mesh.createCloud(start, start + CLOUD_SIZE, layer.height.first, layer.height.last, layer.clouds.flat, cull) + mesh.createCloud(start, start + CLOUD_SIZE, offset, layer.height.first, layer.height.last, layer.clouds.flat, cull) } } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/sky/clouds/CloudLayer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/sky/clouds/CloudLayer.kt index 88a77e64e..b06c2f441 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/sky/clouds/CloudLayer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/sky/clouds/CloudLayer.kt @@ -77,6 +77,10 @@ class CloudLayer( if (offset.y != 0) pushZ(offset.y == 1) } + fun reset() { + + } + private fun reset(cloudPosition: Vec2i) { for (array in arrays.unsafeCast>()) { array?.unload() @@ -92,9 +96,13 @@ class CloudLayer( return this shr 4 } - private fun updatePosition() { + private fun calculateCloudPosition(): Vec2i { val offset = this.offset.toInt() - val position = clouds.connection.player.physics.positionInfo.chunkPosition + Vec2i(offset / CloudArray.CLOUD_SIZE, 0) + return clouds.connection.player.physics.positionInfo.chunkPosition + Vec2i(offset / CloudArray.CLOUD_SIZE, 0) + } + + private fun updatePosition() { + val position = calculateCloudPosition() if (position == this.position) { return } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/sky/clouds/CloudMesh.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/sky/clouds/CloudMesh.kt index 103b21bf8..18291d78c 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/sky/clouds/CloudMesh.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/sky/clouds/CloudMesh.kt @@ -16,6 +16,7 @@ package de.bixilon.minosoft.gui.rendering.sky.clouds import de.bixilon.kotlinglm.vec2.Vec2 import de.bixilon.kotlinglm.vec2.Vec2i import de.bixilon.kotlinglm.vec3.Vec3 +import de.bixilon.kotlinglm.vec3.Vec3i import de.bixilon.minosoft.data.direction.Directions import de.bixilon.minosoft.gui.rendering.RenderContext import de.bixilon.minosoft.gui.rendering.system.base.MeshUtil.buffer @@ -30,9 +31,9 @@ class CloudMesh(context: RenderContext) : Mesh(context, CloudMeshStruct, context } - fun createCloud(start: Vec2i, end: Vec2i, yStart: Int, yEnd: Int, flat: Boolean, culling: BooleanArray) { - val start = Vec3(start.x, yStart, start.y) + CLOUD_OFFSET - val end = Vec3(end.x, yEnd, end.y) + CLOUD_OFFSET + fun createCloud(start: Vec2i, end: Vec2i, offset: Vec3i, yStart: Int, yEnd: Int, flat: Boolean, culling: BooleanArray) { + val start = Vec3(start.x - offset.x, yStart - offset.y, start.y - offset.z) + CLOUD_OFFSET + val end = Vec3(end.x - offset.x, yEnd - offset.y, end.y - offset.z) + CLOUD_OFFSET addYQuad(Vec2(start.x, start.z), start.y, Vec2(end.x, end.z)) { position, _ -> addVertex(position, Directions.DOWN) } if (!flat) { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/sky/clouds/CloudRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/sky/clouds/CloudRenderer.kt index 31e582280..aa6f6af02 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/sky/clouds/CloudRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/sky/clouds/CloudRenderer.kt @@ -63,12 +63,16 @@ class CloudRenderer( var delta = 0.0f private set + private var reset = false + override val skipOpaque: Boolean get() = !sky.effects.clouds || !sky.profile.clouds.enabled || connection.profiles.block.viewDistance < 3 || layers.isEmpty() override fun asyncInit(latch: CountUpAndDownLatch) { matrix.load(connection.assetsManager) + + context.camera.offset::offset.observe(this) { reset() } } private fun getCloudHeight(index: Int): IntRange { @@ -103,6 +107,10 @@ class CloudRenderer( sky.profile.clouds::flat.observe(this, instant = true) { this.flat = it } } + private fun reset() { + reset = true + } + private fun updateLayers(layers: Int) { while (layers < this.layers.size) { toUnload += this.layers.removeLast() @@ -117,6 +125,11 @@ class CloudRenderer( if (!sky.effects.clouds) { return } + if (reset) { + updateLayers(0) + updateLayers(nextLayers) + reset = false + } if (layers.size != nextLayers) { updateLayers(nextLayers) } @@ -218,7 +231,7 @@ class CloudRenderer( private fun setYOffset() { - val y = context.connection.camera.entity.renderInfo.eyePosition.y + val y = (context.connection.camera.entity.renderInfo.eyePosition.y - context.camera.offset.offset.y).toFloat() var yOffset = 0.0f if (baseHeight - y > maxDistance) { yOffset = y - baseHeight + maxDistance @@ -236,8 +249,8 @@ class CloudRenderer( setYOffset() - for (array in layers) { - array.draw() + for (layer in layers) { + layer.draw() } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/sound/AudioPlayer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/sound/AudioPlayer.kt index 8d9e6026d..1c435e37a 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/sound/AudioPlayer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/sound/AudioPlayer.kt @@ -14,6 +14,7 @@ package de.bixilon.minosoft.gui.rendering.sound import de.bixilon.kotlinglm.vec3.Vec3 +import de.bixilon.kotlinglm.vec3.Vec3d import de.bixilon.kutil.collections.CollectionUtil.synchronizedListOf import de.bixilon.kutil.collections.CollectionUtil.toSynchronizedList import de.bixilon.kutil.concurrent.queue.Queue @@ -25,6 +26,7 @@ import de.bixilon.minosoft.gui.rendering.Rendering import de.bixilon.minosoft.gui.rendering.camera.CameraDefinition.CAMERA_UP_VEC3 import de.bixilon.minosoft.gui.rendering.events.CameraPositionChangeEvent import de.bixilon.minosoft.gui.rendering.sound.sounds.Sound +import de.bixilon.minosoft.gui.rendering.util.VecUtil.toVec3 import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.EMPTY import de.bixilon.minosoft.modding.event.listener.CallbackEventListener.Companion.listen import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection @@ -121,7 +123,7 @@ class AudioPlayer( latch.dec() } - override fun playSound(sound: ResourceLocation, position: Vec3?, volume: Float, pitch: Float) { + override fun playSound(sound: ResourceLocation, position: Vec3d?, volume: Float, pitch: Float) { if (!initialized) { return } @@ -180,9 +182,9 @@ class AudioPlayer( return source } - private fun shouldPlay(sound: Sound, position: Vec3?): Boolean { + private fun shouldPlay(sound: Sound, position: Vec3d?): Boolean { if (position == null) return true - val distance = (this.listener.position - position).length2() + val distance = (this.listener.position - position.toVec3).length2() if (distance >= sound.attenuationDistance * sound.attenuationDistance) { return false } @@ -190,7 +192,7 @@ class AudioPlayer( return true } - private fun playSound(sound: Sound, position: Vec3? = null, volume: Float = 1.0f, pitch: Float = 1.0f) { + private fun playSound(sound: Sound, position: Vec3d? = null, volume: Float = 1.0f, pitch: Float = 1.0f) { if (!profile.enabled) { return } @@ -205,7 +207,7 @@ class AudioPlayer( } position?.let { source.relative = false - source.position = it + source.position = it.toVec3 } ?: let { source.position = Vec3.EMPTY source.relative = true diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/sound/DefaultAudioBehavior.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/sound/DefaultAudioBehavior.kt index f64bed425..869eb0bd1 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/sound/DefaultAudioBehavior.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/sound/DefaultAudioBehavior.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2022 Moritz Zwerger + * 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. * @@ -13,7 +13,6 @@ package de.bixilon.minosoft.gui.rendering.sound -import de.bixilon.kotlinglm.vec3.Vec3 import de.bixilon.minosoft.modding.event.events.ExplosionEvent import de.bixilon.minosoft.modding.event.events.PlaySoundEvent import de.bixilon.minosoft.modding.event.listener.CallbackEventListener @@ -29,9 +28,9 @@ object DefaultAudioBehavior { val world = connection.world val invokers = listOf( CallbackEventListener.of { world.playSound(it.soundEvent, it.position, it.volume, it.pitch) }, - CallbackEventListener.of { world.playSound(ENTITY_GENERIC_EXPLODE, Vec3(it.position), 4.0f, (1.0f + (random.nextFloat() - random.nextFloat()) * 0.2f) * 0.7f) }, + CallbackEventListener.of { world.playSound(ENTITY_GENERIC_EXPLODE, it.position, 4.0f, (1.0f + (random.nextFloat() - random.nextFloat()) * 0.2f) * 0.7f) }, ) - connection.register(*invokers.toTypedArray()) + connection.events.register(*invokers.toTypedArray()) } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/system/opengl/OpenGLNativeShader.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/system/opengl/OpenGLNativeShader.kt index 1fcf3667d..49d967725 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/system/opengl/OpenGLNativeShader.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/system/opengl/OpenGLNativeShader.kt @@ -53,12 +53,13 @@ class OpenGLNativeShader( throw ShaderLoadingException() } - glShaderSource(program, code.code) + val glsl = code.code + glShaderSource(program, glsl) glCompileShader(program) if (glGetShaderi(program, GL_COMPILE_STATUS) == GL_FALSE) { - throw ShaderLoadingException(getShaderInfoLog(program)) + throw ShaderLoadingException(getShaderInfoLog(program), glsl) } return program diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/util/mesh/LineMesh.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/util/mesh/LineMesh.kt index 45dabcb9a..fd9a0a9e3 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/util/mesh/LineMesh.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/util/mesh/LineMesh.kt @@ -80,8 +80,9 @@ open class LineMesh(context: RenderContext) : GenericColorMesh(context) { fun drawLazyAABB(aabb: AABB, color: RGBColor) { data.ensureSize(6 * order.size * GenericColorMeshStruct.FLOATS_PER_VERTEX) + val offset = context.camera.offset.offset for (direction in Directions.VALUES) { - val positions = direction.getPositions(Vec3(aabb.min), Vec3(aabb.max)) + val positions = direction.getPositions(Vec3(aabb.min - offset), Vec3(aabb.max - offset)) for ((positionIndex, _) in order) { addVertex(positions[positionIndex], color) } @@ -90,8 +91,9 @@ open class LineMesh(context: RenderContext) : GenericColorMesh(context) { fun drawAABB(aabb: AABB, lineWidth: Float = RenderConstants.DEFAULT_LINE_WIDTH, color: RGBColor, margin: Float = 0.0f, shape: AbstractVoxelShape? = null) { data.ensureSize(12 * 4 * order.size * GenericColorMeshStruct.FLOATS_PER_VERTEX) - val min = aabb.min - margin - val max = aabb.max + margin + val offset = context.camera.offset.offset + val min = aabb.min - margin - offset + val max = aabb.max + margin - offset fun tryDrawLine(start: Vec3, end: Vec3) { tryDrawLine(start, end, lineWidth, color, shape) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/util/vec/vec3/Vec3Util.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/util/vec/vec3/Vec3Util.kt index d83199a88..f17081d0d 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/util/vec/vec3/Vec3Util.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/util/vec/vec3/Vec3Util.kt @@ -156,4 +156,8 @@ object Vec3Util { return Vec3(interpolate(start.x, end.x), interpolate(start.y, end.y), interpolate(start.z, end.z)) } + + fun FloatArray.toVec3(): Vec3 { + return Vec3(this[0], this[1], this[2]) + } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/WorldRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/WorldRenderer.kt index 47e7f4ad1..4ac0d2218 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/WorldRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/WorldRenderer.kt @@ -113,6 +113,7 @@ class WorldRenderer( paused = false } } + context.camera.offset::offset.observe(this) { silentlyClearChunkCache() } context.inputHandler.registerKeyCallback("minosoft:clear_chunk_cache".toResourceLocation(), KeyBinding( KeyActions.MODIFIER to setOf(KeyCodes.KEY_F3), @@ -265,7 +266,7 @@ class WorldRenderer( private fun onFrustumChange() { var sortQueue = false - val cameraPosition = connection.player.renderInfo.eyePosition + val cameraPosition = Vec3(connection.player.renderInfo.eyePosition - context.camera.offset.offset) val cameraChunkPosition = cameraPosition.blockPosition.chunkPosition val cameraSectionHeight = this.cameraSectionHeight if (this.cameraPosition != cameraPosition) { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/border/WorldBorderMesh.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/border/WorldBorderMesh.kt index 9bbb66a30..a183f31ca 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/border/WorldBorderMesh.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/border/WorldBorderMesh.kt @@ -13,51 +13,99 @@ package de.bixilon.minosoft.gui.rendering.world.border +import de.bixilon.kotlinglm.vec2.Vec2 +import de.bixilon.kotlinglm.vec2.Vec2d import de.bixilon.kotlinglm.vec3.Vec3 +import de.bixilon.kotlinglm.vec3.Vec3i +import de.bixilon.minosoft.data.world.World +import de.bixilon.minosoft.data.world.border.WorldBorder import de.bixilon.minosoft.gui.rendering.RenderContext import de.bixilon.minosoft.gui.rendering.system.base.MeshUtil.buffer -import de.bixilon.minosoft.gui.rendering.system.base.buffer.vertex.PrimitiveTypes import de.bixilon.minosoft.gui.rendering.util.mesh.Mesh import de.bixilon.minosoft.gui.rendering.util.mesh.MeshStruct +import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition -class WorldBorderMesh(context: RenderContext) : Mesh(context, WorldBorderMeshStruct, PrimitiveTypes.TRIANGLE, initialCacheSize = 6 * 2 * 3 * WorldBorderMeshStruct.FLOATS_PER_VERTEX) { +class WorldBorderMesh( + context: RenderContext, + val offset: Vec3i, + val center: Vec2d, + val radius: Double, +) : Mesh(context, WorldBorderMeshStruct, initialCacheSize = 6 * 2 * 3 * WorldBorderMeshStruct.FLOATS_PER_VERTEX) { - init { - data.add( - floatArrayOf( - -1.0f, +1.0f, -1.0f, 1.buffer(), - +1.0f, -1.0f, -1.0f, 0.buffer(), - -1.0f, -1.0f, -1.0f, 3.buffer(), - +1.0f, -1.0f, -1.0f, 0.buffer(), - -1.0f, +1.0f, -1.0f, 1.buffer(), - +1.0f, +1.0f, -1.0f, 2.buffer(), - -1.0f, -1.0f, +1.0f, 3.buffer(), - -1.0f, +1.0f, -1.0f, 2.buffer(), - -1.0f, -1.0f, -1.0f, 0.buffer(), - -1.0f, +1.0f, -1.0f, 2.buffer(), - -1.0f, -1.0f, +1.0f, 3.buffer(), - -1.0f, +1.0f, +1.0f, 1.buffer(), - - +1.0f, -1.0f, -1.0f, 3.buffer(), - +1.0f, +1.0f, +1.0f, 2.buffer(), - +1.0f, -1.0f, +1.0f, 0.buffer(), - +1.0f, +1.0f, +1.0f, 2.buffer(), - +1.0f, -1.0f, -1.0f, 3.buffer(), - +1.0f, +1.0f, -1.0f, 1.buffer(), - - -1.0f, -1.0f, +1.0f, 0.buffer(), - +1.0f, +1.0f, +1.0f, 1.buffer(), - -1.0f, +1.0f, +1.0f, 2.buffer(), - +1.0f, +1.0f, +1.0f, 1.buffer(), - -1.0f, -1.0f, +1.0f, 0.buffer(), - +1.0f, -1.0f, +1.0f, 3.buffer(), - )) + private fun width(): Float { + return minOf(radius.toFloat(), World.MAX_RENDER_DISTANCE.toFloat() * ProtocolDefinition.SECTION_WIDTH_X) } + private fun positions(width: Float, center: Double): Array { + val left = (center - width).toFloat() + val right = (center + width).toFloat() + + return arrayOf( + Vec2(left, -1.0f), + Vec2(left, +1.0f), + Vec2(right, +1.0f), + Vec2(right, -1.0f), + ) + } + + private fun textureIndex(index: Int): Int { + return when (index) { + 1 -> 2 + 2 -> 1 + 3 -> 0 + else -> 3 + } + } + + private fun addVertexX(x: Float, width: Float, positions: Array, index: Boolean) { + for ((position, texture) in order) { + val (z, y) = positions[position] + val texture = if (index) textureIndex(texture) else texture + addVertex(x, y, z, textureIndex(texture), width) + } + } + + private fun x(width: Float) { + val positions = positions(width, center.y) + addVertexX((maxOf(-WorldBorder.MAX_RADIUS, center.x - radius) - offset.x).toFloat(), width, positions, false) + addVertexX((minOf(WorldBorder.MAX_RADIUS, center.x + radius) - offset.x).toFloat(), width, positions, true) + } + + private fun addVertexZ(z: Float, width: Float, positions: Array, index: Boolean) { + for ((position, texture) in order) { + val (x, y) = positions[position] + val texture = if (index) textureIndex(texture) else texture + addVertex(x, y, z, textureIndex(texture), width) + } + } + + private fun z(width: Float) { + val positions = positions(width, center.x) + + addVertexZ((maxOf(-WorldBorder.MAX_RADIUS, center.y - radius) - offset.z).toFloat(), width, positions, true) + addVertexZ((minOf(WorldBorder.MAX_RADIUS, center.y + radius) - offset.z).toFloat(), width, positions, false) + } + + fun build() { + val width = width() + x(width) + z(width) + } + + private fun addVertex(x: Float, y: Float, z: Float, uvIndex: Int, width: Float) { + data.add(x) + data.add(y) + data.add(z) + data.add(uvIndex.buffer()) + data.add(width) + } + + data class WorldBorderMeshStruct( val position: Vec3, val uvIndex: Int, + val width: Float, ) { companion object : MeshStruct(WorldBorderMeshStruct::class) } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/border/WorldBorderRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/border/WorldBorderRenderer.kt index 16259693f..76323bf93 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/border/WorldBorderRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/border/WorldBorderRenderer.kt @@ -14,40 +14,46 @@ package de.bixilon.minosoft.gui.rendering.world.border import de.bixilon.kotlinglm.func.common.clamp -import de.bixilon.kotlinglm.vec2.Vec2 import de.bixilon.kutil.latch.CountUpAndDownLatch +import de.bixilon.kutil.observer.DataObserver.Companion.observe import de.bixilon.kutil.time.TimeUtil.millis import de.bixilon.minosoft.data.registries.identified.Namespaces.minosoft +import de.bixilon.minosoft.data.text.formatting.color.RGBColor import de.bixilon.minosoft.data.text.formatting.color.RGBColor.Companion.asColor import de.bixilon.minosoft.data.world.border.WorldBorderState import de.bixilon.minosoft.gui.rendering.RenderContext +import de.bixilon.minosoft.gui.rendering.renderer.renderer.AsyncRenderer import de.bixilon.minosoft.gui.rendering.renderer.renderer.Renderer import de.bixilon.minosoft.gui.rendering.renderer.renderer.RendererBuilder import de.bixilon.minosoft.gui.rendering.system.base.BlendingFunctions import de.bixilon.minosoft.gui.rendering.system.base.RenderSystem +import de.bixilon.minosoft.gui.rendering.system.base.phases.SkipAll import de.bixilon.minosoft.gui.rendering.system.base.phases.TranslucentDrawable import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.texture +import de.bixilon.minosoft.gui.rendering.util.mesh.Mesh import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection import de.bixilon.minosoft.util.KUtil.toResourceLocation class WorldBorderRenderer( override val context: RenderContext, -) : Renderer, TranslucentDrawable { +) : Renderer, AsyncRenderer, TranslucentDrawable, SkipAll { override val renderSystem: RenderSystem = context.renderSystem private val shader = renderSystem.createShader(minosoft("world/border")) { WorldBorderShader(it) } - private val borderMesh = WorldBorderMesh(context) + private var borderMesh: WorldBorderMesh? = null private val border = context.connection.world.border private lateinit var texture: AbstractTexture private var offsetReset = millis() - override val skipTranslucent: Boolean + override val skipAll: Boolean get() = border.getDistanceTo(context.connection.player.physics.position) > MAX_DISTANCE + private var reload = false override fun init(latch: CountUpAndDownLatch) { + shader.native.defines["MAX_DISTANCE"] = MAX_DISTANCE shader.load() - borderMesh.load() texture = context.textureManager.staticTextures.createTexture(TEXTURE) + context.camera.offset::offset.observe(this) { reload = true } } override fun postInit(latch: CountUpAndDownLatch) { @@ -55,7 +61,53 @@ class WorldBorderRenderer( shader.textureIndexLayer = texture.renderData.shaderTextureId } + private fun calculateColor(): RGBColor { + val distance = border.getDistanceTo(context.connection.player.physics.position).toFloat() - 1.0f // 1 block padding + val strength = 1.0f - distance.clamp(0.0f, MAX_DISTANCE) / MAX_DISTANCE // slowly fade in + val color = when (border.area.state) { + WorldBorderState.GROWING -> GROWING_COLOR + WorldBorderState.SHRINKING -> SHRINKING_COLOR + WorldBorderState.STATIC -> STATIC_COLOR + } + return color.with(alpha = (strength * strength)) + } + + private fun update() { + if (this.borderMesh == null) return + + val time = millis() + if (offsetReset - time > ANIMATION_SPEED) { + offsetReset = time + } + val textureOffset = (offsetReset - time) / ANIMATION_SPEED.toFloat() + shader.textureOffset = 1.0f - textureOffset + + shader.tintColor = calculateColor() + } + + + override fun prepareDrawAsync() { + if (skipAll) return + + val center = border.center + val radius = border.area.radius() + + val previous = this.borderMesh + if (previous != null && !reload && center == previous.center && radius == previous.radius) return + + context.queue += { previous?.unload() } + + val offset = context.camera.offset.offset + + val mesh = WorldBorderMesh(context, offset, center, radius) + mesh.build() + + this.borderMesh = mesh + this.reload = false + } + override fun setupTranslucent() { + val mesh = this.borderMesh ?: return renderSystem.reset( blending = true, sourceRGB = BlendingFunctions.SOURCE_ALPHA, @@ -68,29 +120,15 @@ class WorldBorderRenderer( polygonOffsetUnit = -3.0f, ) shader.use() - val time = millis() - if (offsetReset - time > ANIMATION_SPEED) { - offsetReset = time - } - val textureOffset = (offsetReset - time) / ANIMATION_SPEED.toFloat() - shader.textureOffset = 1.0f - textureOffset - shader.cameraHeight = context.connection.camera.entity.renderInfo.eyePosition.y + update() - val distance = border.getDistanceTo(context.connection.player.physics.position) - val strength = 1.0f - (distance.toFloat().clamp(0.0f, 100.0f) / 100.0f) - var color = when (border.state) { - WorldBorderState.GROWING -> GROWING_COLOR - WorldBorderState.SHRINKING -> SHRINKING_COLOR - WorldBorderState.STATIC -> STATIC_COLOR + if (mesh.state == Mesh.MeshStates.PREPARING) { + mesh.load() } - color = color.with(alpha = (strength * strength)) - shader.tintColor = color - shader.radius = border.diameter.toFloat() / 2.0f - shader.center = Vec2(border.center) } override fun drawTranslucent() { - borderMesh.draw() + borderMesh?.draw() } companion object : RendererBuilder { @@ -99,7 +137,7 @@ class WorldBorderRenderer( val SHRINKING_COLOR = "#FF3030".asColor() val STATIC_COLOR = "#20A0FF".asColor() const val ANIMATION_SPEED = 2000 - const val MAX_DISTANCE = 1000 + const val MAX_DISTANCE = 100.0f private val TEXTURE = "minecraft:misc/forcefield".toResourceLocation().texture() diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/border/WorldBorderShader.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/border/WorldBorderShader.kt index caa4c95f0..e9ec90662 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/border/WorldBorderShader.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/border/WorldBorderShader.kt @@ -14,21 +14,20 @@ package de.bixilon.minosoft.gui.rendering.world.border import de.bixilon.kotlinglm.mat4x4.Mat4 -import de.bixilon.kotlinglm.vec2.Vec2 import de.bixilon.kotlinglm.vec3.Vec3 import de.bixilon.minosoft.data.text.formatting.color.ChatColors import de.bixilon.minosoft.gui.rendering.camera.FogManager import de.bixilon.minosoft.gui.rendering.shader.Shader +import de.bixilon.minosoft.gui.rendering.shader.types.CameraPositionShader import de.bixilon.minosoft.gui.rendering.shader.types.FogShader import de.bixilon.minosoft.gui.rendering.shader.types.TextureShader import de.bixilon.minosoft.gui.rendering.shader.types.ViewProjectionShader import de.bixilon.minosoft.gui.rendering.system.base.shader.NativeShader import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureManager -import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2Util.EMPTY class WorldBorderShader( override val native: NativeShader, -) : Shader(), TextureShader, ViewProjectionShader, FogShader { +) : Shader(), TextureShader, ViewProjectionShader, FogShader, CameraPositionShader { override var textures: TextureManager by textureManager() override var viewProjectionMatrix: Mat4 by viewProjectionMatrix() override var cameraPosition: Vec3 by cameraPosition() @@ -38,7 +37,4 @@ class WorldBorderShader( var textureIndexLayer by uniform("uIndexLayer", 0, NativeShader::setUInt) var textureOffset by uniform("uTextureOffset", 0.0f) - var radius by uniform("uRadius", 0.0f) - var center by uniform("uCenter", Vec2.EMPTY) - var cameraHeight by uniform("uCameraHeight", 0.0f) } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/chunk/ChunkBorderRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/chunk/ChunkBorderRenderer.kt index 88b66b498..9d3418e80 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/chunk/ChunkBorderRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/chunk/ChunkBorderRenderer.kt @@ -31,7 +31,8 @@ import de.bixilon.minosoft.gui.rendering.renderer.renderer.RendererBuilder import de.bixilon.minosoft.gui.rendering.system.base.RenderSystem import de.bixilon.minosoft.gui.rendering.system.base.phases.OpaqueDrawable import de.bixilon.minosoft.gui.rendering.util.mesh.LineMesh -import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.blockPosition +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3dUtil.blockPosition +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.EMPTY import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.chunkPosition import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.sectionHeight import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection @@ -45,6 +46,7 @@ class ChunkBorderRenderer( ) : AsyncRenderer, OpaqueDrawable, MeshSwapper { private val profile = connection.profiles.rendering override val renderSystem: RenderSystem = context.renderSystem + private var offset = Vec3i.EMPTY private var chunkPosition: Vec2i? = null private var sectionHeight: Int = Int.MIN_VALUE @@ -77,52 +79,54 @@ class ChunkBorderRenderer( val eyePosition = connection.camera.entity.renderInfo.eyePosition.blockPosition val chunkPosition = eyePosition.chunkPosition val sectionHeight = eyePosition.sectionHeight - if (chunkPosition == this.chunkPosition && sectionHeight == this.sectionHeight && mesh != null) { + val offset = context.camera.offset.offset + if (chunkPosition == this.chunkPosition && sectionHeight == this.sectionHeight && this.offset == offset && mesh != null) { return } unload = true val mesh = LineMesh(context) val dimension = context.connection.world.dimension - val basePosition = chunkPosition * Vec2i(ProtocolDefinition.SECTION_WIDTH_X, ProtocolDefinition.SECTION_WIDTH_Z) + val basePosition = chunkPosition * Vec2i(ProtocolDefinition.SECTION_WIDTH_X, ProtocolDefinition.SECTION_WIDTH_Z) - Vec2i(offset.x, offset.z) - mesh.drawInnerChunkLines(basePosition, dimension) + mesh.drawInnerChunkLines(Vec3i(basePosition.x, -offset.y, basePosition.y), dimension) if (sectionHeight in dimension.minSection until dimension.maxSection) { mesh.drawSectionLines(Vec3i(basePosition.x, sectionHeight * ProtocolDefinition.SECTION_HEIGHT_Y, basePosition.y)) } - mesh.drawOuterChunkLines(chunkPosition, dimension) + mesh.drawOuterChunkLines(chunkPosition, offset, dimension) - this.nextMesh = mesh this.chunkPosition = chunkPosition this.sectionHeight = sectionHeight + this.offset = offset + this.nextMesh = mesh } - private fun LineMesh.drawOuterChunkLines(chunkPosition: Vec2i, dimension: DimensionProperties) { + private fun LineMesh.drawOuterChunkLines(chunkPosition: Vec2i, offset: Vec3i, dimension: DimensionProperties) { for (x in -OUTER_CHUNK_SIZE..OUTER_CHUNK_SIZE + 1) { for (z in -OUTER_CHUNK_SIZE..OUTER_CHUNK_SIZE + 1) { if ((x == 0 || x == 1) && (z == 0 || z == 1)) { continue } - val chunkBase = (chunkPosition + Vec2i(x, z)) * Vec2i(ProtocolDefinition.SECTION_WIDTH_X, ProtocolDefinition.SECTION_WIDTH_Z) - drawLine(Vec3(chunkBase.x + 0, dimension.minY, chunkBase.y), Vec3(chunkBase.x + 0, dimension.maxY + 1, chunkBase.y), OUTER_CHUNK_LINE_WIDTH, OUTER_CHUNK_COLOR) + val chunkBase = (chunkPosition + Vec2i(x, z)) * Vec2i(ProtocolDefinition.SECTION_WIDTH_X, ProtocolDefinition.SECTION_WIDTH_Z) - Vec2i(offset.x, offset.z) + drawLine(Vec3(chunkBase.x + 0, dimension.minY - offset.y, chunkBase.y), Vec3(chunkBase.x + 0, dimension.maxY - offset.y + 1, chunkBase.y), OUTER_CHUNK_LINE_WIDTH, OUTER_CHUNK_COLOR) } } } - private fun LineMesh.drawInnerChunkLines(basePosition: Vec2i, dimension: DimensionProperties) { - drawLine(Vec3(basePosition.x + 0, dimension.minY, basePosition.y), Vec3(basePosition.x + 0, dimension.maxY + 1, basePosition.y), INNER_CHUNK_LINE_WIDTH, INNER_CHUNK_COLOR) - drawLine(Vec3(basePosition.x, dimension.minY, basePosition.y + ProtocolDefinition.SECTION_WIDTH_Z), Vec3(basePosition.x, dimension.maxY + 1, basePosition.y + ProtocolDefinition.SECTION_WIDTH_Z), INNER_CHUNK_LINE_WIDTH, INNER_CHUNK_COLOR) - drawLine(Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, dimension.minY, basePosition.y + 0), Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, dimension.maxY + 1, basePosition.y + 0), INNER_CHUNK_LINE_WIDTH, INNER_CHUNK_COLOR) - drawLine(Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, dimension.minY, basePosition.y + ProtocolDefinition.SECTION_WIDTH_Z), Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, dimension.maxY + 1, basePosition.y + ProtocolDefinition.SECTION_WIDTH_Z), INNER_CHUNK_LINE_WIDTH, INNER_CHUNK_COLOR) + private fun LineMesh.drawInnerChunkLines(basePosition: Vec3i, dimension: DimensionProperties) { + drawLine(Vec3(basePosition.x + 0, basePosition.y + dimension.minY, basePosition.z), Vec3(basePosition.x + 0, basePosition.y + dimension.maxY + 1, basePosition.z), INNER_CHUNK_LINE_WIDTH, INNER_CHUNK_COLOR) + drawLine(Vec3(basePosition.x, basePosition.y + dimension.minY, basePosition.z + ProtocolDefinition.SECTION_WIDTH_Z), Vec3(basePosition.x, basePosition.y + dimension.maxY + 1, basePosition.z + ProtocolDefinition.SECTION_WIDTH_Z), INNER_CHUNK_LINE_WIDTH, INNER_CHUNK_COLOR) + drawLine(Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, basePosition.y + dimension.minY, basePosition.z + 0), Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, basePosition.y + dimension.maxY + 1, basePosition.z + 0), INNER_CHUNK_LINE_WIDTH, INNER_CHUNK_COLOR) + drawLine(Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, basePosition.y + dimension.minY, basePosition.z + ProtocolDefinition.SECTION_WIDTH_Z), Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, basePosition.y + dimension.maxY + 1, basePosition.z + ProtocolDefinition.SECTION_WIDTH_Z), INNER_CHUNK_LINE_WIDTH, INNER_CHUNK_COLOR) for (sectionHeight in dimension.minSection..dimension.maxSection) { - val y = sectionHeight * ProtocolDefinition.SECTION_HEIGHT_Y - drawLine(Vec3(basePosition.x, y, basePosition.y), Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, y, basePosition.y), INNER_CHUNK_LINE_WIDTH, INNER_CHUNK_COLOR) - drawLine(Vec3(basePosition.x, y, basePosition.y), Vec3(basePosition.x, y, basePosition.y + ProtocolDefinition.SECTION_WIDTH_Z), INNER_CHUNK_LINE_WIDTH, INNER_CHUNK_COLOR) - 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), INNER_CHUNK_LINE_WIDTH, INNER_CHUNK_COLOR) - 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), INNER_CHUNK_LINE_WIDTH, INNER_CHUNK_COLOR) + val y = basePosition.y + sectionHeight * ProtocolDefinition.SECTION_HEIGHT_Y + drawLine(Vec3(basePosition.x, y, basePosition.z), Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, y, basePosition.z), INNER_CHUNK_LINE_WIDTH, INNER_CHUNK_COLOR) + drawLine(Vec3(basePosition.x, y, basePosition.z), Vec3(basePosition.x, y, basePosition.z + ProtocolDefinition.SECTION_WIDTH_Z), INNER_CHUNK_LINE_WIDTH, INNER_CHUNK_COLOR) + drawLine(Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, y, basePosition.z + ProtocolDefinition.SECTION_WIDTH_Z), Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, y, basePosition.z), INNER_CHUNK_LINE_WIDTH, INNER_CHUNK_COLOR) + drawLine(Vec3(basePosition.x + ProtocolDefinition.SECTION_WIDTH_X, y, basePosition.z + ProtocolDefinition.SECTION_WIDTH_Z), Vec3(basePosition.x, y, basePosition.z + ProtocolDefinition.SECTION_WIDTH_Z), INNER_CHUNK_LINE_WIDTH, INNER_CHUNK_COLOR) } } @@ -186,7 +190,11 @@ class ChunkBorderRenderer( } override fun setupOpaque() { - context.renderSystem.reset() + context.renderSystem.reset( + polygonOffset = true, + polygonOffsetFactor = -1.0f, + polygonOffsetUnit = -2.0f, + ) context.shaderManager.genericColorShader.use() } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/entities/renderer/sign/SignBlockEntityRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/entities/renderer/sign/SignBlockEntityRenderer.kt index 967ced78a..9b1ef0ee0 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/entities/renderer/sign/SignBlockEntityRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/entities/renderer/sign/SignBlockEntityRenderer.kt @@ -32,8 +32,8 @@ import de.bixilon.minosoft.gui.rendering.RenderContext import de.bixilon.minosoft.gui.rendering.font.Font import de.bixilon.minosoft.gui.rendering.font.renderer.ChatComponentRenderer import de.bixilon.minosoft.gui.rendering.models.unbaked.element.UnbakedElement -import de.bixilon.minosoft.gui.rendering.util.VecUtil.toVec3 import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.rotateAssign +import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.toVec3 import de.bixilon.minosoft.gui.rendering.world.entities.OnlyMeshedBlockEntityRenderer import de.bixilon.minosoft.gui.rendering.world.mesh.SingleWorldMesh import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh @@ -52,19 +52,19 @@ class SignBlockEntityRenderer( return rotation * 22.5f } - override fun singleRender(position: Vec3i, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array, light: ByteArray, tints: IntArray?): Boolean { + override fun singleRender(position: Vec3i, offset: FloatArray, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array, light: ByteArray, tints: IntArray?): Boolean { val block = this.blockState.block if (block is StandingSignBlock) { - renderStandingText(position, mesh, light[SolidCullSectionPreparer.SELF_LIGHT_INDEX].toInt()) + renderStandingText(offset, mesh, light[SolidCullSectionPreparer.SELF_LIGHT_INDEX].toInt()) } else if (block is WallSignBlock) { - renderWallText(position, mesh, light[SolidCullSectionPreparer.SELF_LIGHT_INDEX].toInt()) + renderWallText(offset, mesh, light[SolidCullSectionPreparer.SELF_LIGHT_INDEX].toInt()) } return true } - private fun renderText(position: Vec3i, rotationVector: Vec3, yRotation: Float, mesh: WorldMesh, light: Int) { - val textPosition = position.toVec3 + rotationVector + private fun renderText(offset: FloatArray, rotationVector: Vec3, yRotation: Float, mesh: WorldMesh, light: Int) { + val textPosition = offset.toVec3() + rotationVector val textMesh = mesh.textMesh!! var primitives = 0 @@ -79,15 +79,15 @@ class SignBlockEntityRenderer( } } - private fun renderStandingText(position: Vec3i, mesh: WorldMesh, light: Int) { + private fun renderStandingText(offset: FloatArray, mesh: WorldMesh, light: Int) { val yRotation = getRotation() val rotationVector = Vec3(X_OFFSET, 17.5f / UnbakedElement.BLOCK_RESOLUTION - Y_OFFSET, 9.0f / UnbakedElement.BLOCK_RESOLUTION + Z_OFFSET) rotationVector.signRotate(yRotation.rad) - renderText(position, rotationVector, yRotation, mesh, light) + renderText(offset, rotationVector, yRotation, mesh, light) } - private fun renderWallText(position: Vec3i, mesh: WorldMesh, light: Int) { + private fun renderWallText(position: FloatArray, mesh: WorldMesh, light: Int) { val yRotation = -when (val rotation = this.blockState.getFacing()) { Directions.SOUTH -> 0.0f Directions.EAST -> 90.0f diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/entities/renderer/storage/DoubleChestRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/entities/renderer/storage/DoubleChestRenderer.kt index cd41c6df3..6ecfe1257 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/entities/renderer/storage/DoubleChestRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/entities/renderer/storage/DoubleChestRenderer.kt @@ -38,7 +38,7 @@ class DoubleChestRenderer( light: Int, ) : StorageBlockEntityRenderer( blockState, - SkeletalInstance(context, model, blockPosition.toVec3, (blockState.getFacing()).rotatedMatrix), + SkeletalInstance(context, model, (blockPosition - context.camera.offset.offset).toVec3, (blockState.getFacing()).rotatedMatrix), light, ) { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/entities/renderer/storage/SingleChestRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/entities/renderer/storage/SingleChestRenderer.kt index f774ae9fd..141d17403 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/entities/renderer/storage/SingleChestRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/entities/renderer/storage/SingleChestRenderer.kt @@ -38,7 +38,7 @@ class SingleChestRenderer( light: Int, ) : StorageBlockEntityRenderer( blockState, - SkeletalInstance(context, model, blockPosition.toVec3, blockState.getFacing().rotatedMatrix), + SkeletalInstance(context, model, (blockPosition - context.camera.offset.offset).toVec3, blockState.getFacing().rotatedMatrix), light, ) { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/outline/BlockOutlineRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/outline/BlockOutlineRenderer.kt index 6751524ff..a1ee6b15b 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/outline/BlockOutlineRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/outline/BlockOutlineRenderer.kt @@ -63,7 +63,6 @@ class BlockOutlineRenderer( override var unload: Boolean = false override fun init(latch: CountUpAndDownLatch) { - val profile = connection.profiles.block this.profile::enabled.observe(this) { reload = true } this.profile::collisions.observe(this) { reload = true } this.profile::outlineColor.observe(this) { reload = true } @@ -77,7 +76,11 @@ class BlockOutlineRenderer( } override fun setupOther() { - context.renderSystem.reset() + context.renderSystem.reset( + polygonOffset = true, + polygonOffsetFactor = -3.0f, + polygonOffsetUnit = -3.0f, + ) if (profile.showThroughWalls) { context.renderSystem.depth = DepthFunctions.ALWAYS } @@ -113,7 +116,9 @@ class BlockOutlineRenderer( } } - if (target.blockPosition == position && target.state == state && !reload) { // TODO: also compare shapes, some blocks dynamically change it (e.g. scaffolding) + val offsetPosition = (target.blockPosition - context.camera.offset.offset) + + if (offsetPosition == position && target.state == state && !reload) { // TODO: also compare shapes, some blocks dynamically change it (e.g. scaffolding) return } @@ -139,7 +144,7 @@ class BlockOutlineRenderer( this.nextMesh = mesh - this.position = target.blockPosition + this.position = offsetPosition this.state = target.state this.reload = false } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/cull/FluidCullSectionPreparer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/cull/FluidCullSectionPreparer.kt index f7f8f710a..e16a5e5ae 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/cull/FluidCullSectionPreparer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/cull/FluidCullSectionPreparer.kt @@ -68,6 +68,8 @@ class FluidCullSectionPreparer( var rendered = false var tint: Int + val cameraOffset = context.camera.offset.offset + val offsetX = chunkPosition.x * ProtocolDefinition.SECTION_WIDTH_X val offsetY = sectionHeight * ProtocolDefinition.SECTION_HEIGHT_Y val offsetZ = chunkPosition.y * ProtocolDefinition.SECTION_WIDTH_Z @@ -130,6 +132,8 @@ class FluidCullSectionPreparer( getCornerHeight(chunk, chunkPosition, position + Directions.SOUTH, fluid), ) + val offsetPosition = Vec3(position - cameraOffset) + if (!skip[Directions.O_UP]) { val velocity = fluid.getVelocity(blockState, position, chunk) val still = velocity.x == 0.0 && velocity.z == 0.0 @@ -164,10 +168,10 @@ class FluidCullSectionPreparer( val meshToUse = texture.transparency.getMesh(mesh) val positions = arrayOf( - Vec3(position.x, position.y + cornerHeights[0], position.z), - Vec3(position.x + 1, position.y + cornerHeights[1], position.z), - Vec3(position.x + 1, position.y + cornerHeights[2], position.z + 1), - Vec3(position.x, position.y + cornerHeights[3], position.z + 1), + Vec3(offsetPosition.x, offsetPosition.y + cornerHeights[0], offsetPosition.z), + Vec3(offsetPosition.x + 1, offsetPosition.y + cornerHeights[1], offsetPosition.z), + Vec3(offsetPosition.x + 1, offsetPosition.y + cornerHeights[2], offsetPosition.z + 1), + Vec3(offsetPosition.x, offsetPosition.y + cornerHeights[3], offsetPosition.z + 1), ) @@ -182,9 +186,9 @@ class FluidCullSectionPreparer( if (skip[Directions.SIDE_OFFSET + direction]) { continue } - var faceX = position.x.toFloat() + var faceX = offsetPosition.x var faceXEnd = faceX - var faceZ = position.z.toFloat() + var faceZ = offsetPosition.z var faceZEnd = faceZ var v1 = 0.0f var v2 = 0.0f @@ -222,10 +226,10 @@ class FluidCullSectionPreparer( val positions = arrayOf( - Vec3(faceX, position.y + v1, faceZ), - Vec3(faceX, position.y, faceZ), - Vec3(faceXEnd, position.y, faceZEnd), - Vec3(faceXEnd, position.y + v2, faceZEnd), + Vec3(faceX, offsetPosition.y + v1, faceZ), + Vec3(faceX, offsetPosition.y, faceZ), + Vec3(faceXEnd, offsetPosition.y, faceZEnd), + Vec3(faceXEnd, offsetPosition.y + v2, faceZEnd), ) val texturePositions = arrayOf( TEXTURE_1, diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/cull/SolidCullSectionPreparer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/cull/SolidCullSectionPreparer.kt index 7251ae05d..d14b3593d 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/cull/SolidCullSectionPreparer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/cull/SolidCullSectionPreparer.kt @@ -76,15 +76,21 @@ class SolidCullSectionPreparer( val neighbourBlocks: Array = arrayOfNulls(Directions.SIZE) val light = ByteArray(Directions.SIZE + 1) // last index (6) for the current block + val cameraOffset = context.camera.offset.offset + val offsetX = chunkPosition.x * ProtocolDefinition.SECTION_WIDTH_X val offsetY = sectionHeight * ProtocolDefinition.SECTION_HEIGHT_Y val offsetZ = chunkPosition.y * ProtocolDefinition.SECTION_WIDTH_Z + val floatOffset = FloatArray(3) + for (y in blocks.minPosition.y..blocks.maxPosition.y) { position.y = offsetY + y + floatOffset[1] = (position.y - cameraOffset.y).toFloat() val fastBedrock = y == 0 && isLowestSection && fastBedrock for (x in blocks.minPosition.x..blocks.maxPosition.x) { position.x = offsetX + x + floatOffset[0] = (position.x - cameraOffset.x).toFloat() for (z in blocks.minPosition.z..blocks.maxPosition.z) { val baseIndex = (z shl 4) or x val index = (y shl 8) or baseIndex @@ -94,6 +100,7 @@ class SolidCullSectionPreparer( } light[SELF_LIGHT_INDEX] = sectionLight[index] position.z = offsetZ + z + floatOffset[2] = (position.z - cameraOffset.z).toFloat() val maxHeight = chunk.light.heightmap[baseIndex] if (position.y >= maxHeight) { @@ -158,10 +165,10 @@ class SolidCullSectionPreparer( random.setSeed(0L) } tints = tintColorCalculator.getAverageBlockTint(chunk, neighbourChunks, blockState, x, y, z) - rendered = model.singleRender(position, mesh, random, blockState, neighbourBlocks, light, tints) + rendered = model.singleRender(position, floatOffset, mesh, random, blockState, neighbourBlocks, light, tints) if (blockEntityModel is MeshedBlockEntityRenderer<*>) { - rendered = blockEntityModel.singleRender(position, mesh, random, blockState, neighbourBlocks, light, tints) || rendered + rendered = blockEntityModel.singleRender(position, floatOffset, mesh, random, blockState, neighbourBlocks, light, tints) || rendered } if (rendered) { diff --git a/src/main/java/de/bixilon/minosoft/modding/event/events/PlaySoundEvent.kt b/src/main/java/de/bixilon/minosoft/modding/event/events/PlaySoundEvent.kt index c8861f16d..d2d36b9ca 100644 --- a/src/main/java/de/bixilon/minosoft/modding/event/events/PlaySoundEvent.kt +++ b/src/main/java/de/bixilon/minosoft/modding/event/events/PlaySoundEvent.kt @@ -13,7 +13,7 @@ package de.bixilon.minosoft.modding.event.events -import de.bixilon.kotlinglm.vec3.Vec3 +import de.bixilon.kotlinglm.vec3.Vec3d import de.bixilon.minosoft.data.SoundCategories import de.bixilon.minosoft.data.registries.identified.ResourceLocation import de.bixilon.minosoft.modding.event.events.connection.play.PlayConnectionEvent @@ -24,15 +24,15 @@ import de.bixilon.minosoft.protocol.packets.s2c.play.sound.SoundEventS2CP class PlaySoundEvent( connection: PlayConnection, val category: SoundCategories?, - position: Vec3, + position: Vec3d, val soundEvent: ResourceLocation, val volume: Float, val pitch: Float, ) : PlayConnectionEvent(connection), CancelableEvent { - val position: Vec3 = position - get() = Vec3(field) + val position: Vec3d = position + get() = Vec3d(field) - constructor(connection: PlayConnection, packet: SoundEventS2CP) : this(connection, packet.category, Vec3(packet.position), packet.sound, packet.volume, packet.pitch.toFloat()) + constructor(connection: PlayConnection, packet: SoundEventS2CP) : this(connection, packet.category, packet.position, packet.sound, packet.volume, packet.pitch) - constructor(connection: PlayConnection, packet: NamedSoundS2CP) : this(connection, packet.category, packet.position, packet.soundEvent!!, packet.volume, packet.pitch.toFloat()) + constructor(connection: PlayConnection, packet: NamedSoundS2CP) : this(connection, packet.category, packet.position, packet.soundEvent!!, packet.volume, packet.pitch) } diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/border/InitializeWorldBorderS2CP.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/border/InitializeWorldBorderS2CP.kt index a30c7fb99..08b50af3d 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/border/InitializeWorldBorderS2CP.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/border/InitializeWorldBorderS2CP.kt @@ -23,8 +23,8 @@ import de.bixilon.minosoft.util.logging.LogMessageType @LoadPacket(parent = true) class InitializeWorldBorderS2CP(buffer: PlayInByteBuffer) : WorldBorderS2CP { val center = buffer.readVec2d() - val oldDiameter = buffer.readDouble() - val newDiameter = buffer.readDouble() + val oldRadius = buffer.readDouble() / 2.0 + val newRadius = buffer.readDouble() / 2.0 val millis = buffer.readVarLong() val portalBound = buffer.readVarInt() val warningTime = buffer.readVarInt() @@ -32,13 +32,13 @@ class InitializeWorldBorderS2CP(buffer: PlayInByteBuffer) : WorldBorderS2CP { override fun handle(connection: PlayConnection) { connection.world.border.center = center - connection.world.border.interpolate(oldDiameter, newDiameter, millis) + connection.world.border.interpolate(oldRadius, newRadius, millis) connection.world.border.portalBound = portalBound connection.world.border.warningTime = warningTime connection.world.border.warningBlocks = warningBlocks } override fun log(reducedLog: Boolean) { - Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "Initialize world border (center=$center, oldDiameter=$oldDiameter, newDiameter=$newDiameter, speed=$millis, portalBound=$portalBound, warningTime=$warningTime, warningBlocks=$warningBlocks)" } + Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "Initialize world border (center=$center, oldRadius=$oldRadius, newRadius=$newRadius, speed=$millis, portalBound=$portalBound, warningTime=$warningTime, warningBlocks=$warningBlocks)" } } } diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/border/InterpolateWorldBorderS2CP.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/border/InterpolateWorldBorderS2CP.kt index 7335eb9cb..409a828a6 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/border/InterpolateWorldBorderS2CP.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/border/InterpolateWorldBorderS2CP.kt @@ -22,15 +22,15 @@ import de.bixilon.minosoft.util.logging.LogMessageType @LoadPacket(parent = true) class InterpolateWorldBorderS2CP(buffer: PlayInByteBuffer) : WorldBorderS2CP { - val oldDiameter = buffer.readDouble() - val newDiameter = buffer.readDouble() + val oldRadius = buffer.readDouble() / 2.0 + val newRadius = buffer.readDouble() / 2.0 val millis = buffer.readVarLong() override fun handle(connection: PlayConnection) { - connection.world.border.interpolate(oldDiameter, newDiameter, millis) + connection.world.border.interpolate(oldRadius, newRadius, millis) } override fun log(reducedLog: Boolean) { - Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "Interpolate size world border (oldDiameter=$oldDiameter, newDiameter=$newDiameter, millis=$millis)" } + Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "Interpolate size world border (oldRadius=$oldRadius, newRadius=$newRadius, millis=$millis)" } } } diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/border/SizeWorldBorderS2CP.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/border/SizeWorldBorderS2CP.kt index bf618b6e0..c42872c75 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/border/SizeWorldBorderS2CP.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/border/SizeWorldBorderS2CP.kt @@ -13,6 +13,7 @@ package de.bixilon.minosoft.protocol.packets.s2c.play.border +import de.bixilon.minosoft.data.world.border.area.StaticBorderArea import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection import de.bixilon.minosoft.protocol.packets.factory.LoadPacket import de.bixilon.minosoft.protocol.protocol.buffers.play.PlayInByteBuffer @@ -22,14 +23,13 @@ import de.bixilon.minosoft.util.logging.LogMessageType @LoadPacket(parent = true) class SizeWorldBorderS2CP(buffer: PlayInByteBuffer) : WorldBorderS2CP { - val diameter = buffer.readDouble() + val radius = buffer.readDouble() / 2.0 override fun handle(connection: PlayConnection) { - connection.world.border.stopInterpolating() - connection.world.border.diameter = diameter + connection.world.border.area = StaticBorderArea(radius) } override fun log(reducedLog: Boolean) { - Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "Size set world border (diameter=$diameter)" } + Log.log(LogMessageType.NETWORK_PACKETS_IN, level = LogLevels.VERBOSE) { "Size set world border (radius=$radius)" } } } diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/sound/NamedSoundS2CP.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/sound/NamedSoundS2CP.kt index d277dc699..35af3fadd 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/sound/NamedSoundS2CP.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/sound/NamedSoundS2CP.kt @@ -12,7 +12,7 @@ */ package de.bixilon.minosoft.protocol.packets.s2c.play.sound -import de.bixilon.kotlinglm.vec3.Vec3 +import de.bixilon.kotlinglm.vec3.Vec3d import de.bixilon.minosoft.data.SoundCategories import de.bixilon.minosoft.data.registries.identified.ResourceLocation import de.bixilon.minosoft.modding.event.events.PlaySoundEvent @@ -33,7 +33,7 @@ class NamedSoundS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket { val soundEvent: ResourceLocation? val volume: Float val pitch: Float - lateinit var position: Vec3 + lateinit var position: Vec3d private set lateinit var category: SoundCategories private set @@ -49,13 +49,13 @@ class NamedSoundS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket { buffer.readString() // parrot entity type } if (buffer.versionId < V_16W02A) { - position = Vec3(buffer.readInt() * 8, buffer.readInt() * 8, buffer.readInt() * 8) // ToDo: check if it is not * 4 + position = Vec3d(buffer.readInt() * 4, buffer.readInt() * 4, buffer.readInt() * 4) } if (buffer.versionId >= V_16W02A && (buffer.versionId !in V_17W15A until V_17W18A)) { this.category = SoundCategories[buffer.readVarInt()] } if (buffer.versionId >= V_16W02A) { - position = Vec3(buffer.readFixedPointNumberInt() * 4, buffer.readFixedPointNumberInt() * 4, buffer.readFixedPointNumberInt() * 4) + position = Vec3d(buffer.readFixedPointNumberInt() * 4, buffer.readFixedPointNumberInt() * 4, buffer.readFixedPointNumberInt() * 4) } volume = buffer.readFloat() pitch = buffer.readSoundPitch() diff --git a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/sound/SoundEventS2CP.kt b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/sound/SoundEventS2CP.kt index 9125f935e..2e95fd043 100644 --- a/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/sound/SoundEventS2CP.kt +++ b/src/main/java/de/bixilon/minosoft/protocol/packets/s2c/play/sound/SoundEventS2CP.kt @@ -12,7 +12,7 @@ */ package de.bixilon.minosoft.protocol.packets.s2c.play.sound -import de.bixilon.kotlinglm.vec3.Vec3i +import de.bixilon.kotlinglm.vec3.Vec3d import de.bixilon.minosoft.data.SoundCategories import de.bixilon.minosoft.data.registries.identified.ResourceLocation import de.bixilon.minosoft.modding.event.events.PlaySoundEvent @@ -33,7 +33,7 @@ import de.bixilon.minosoft.util.logging.LogMessageType class SoundEventS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket { var category: SoundCategories? = null private set - val position: Vec3i + val position: Vec3d val sound: ResourceLocation val volume: Float val pitch: Float @@ -65,7 +65,7 @@ class SoundEventS2CP(buffer: PlayInByteBuffer) : PlayS2CPacket { if (buffer.versionId >= V_16W02A && (buffer.versionId !in V_17W15A until V_17W18A)) { this.category = SoundCategories[buffer.readVarInt()] } - position = Vec3i(buffer.readFixedPointNumberInt() * 4, buffer.readFixedPointNumberInt() * 4, buffer.readFixedPointNumberInt() * 4) + position = Vec3d(buffer.readFixedPointNumberInt() * 4, buffer.readFixedPointNumberInt() * 4, buffer.readFixedPointNumberInt() * 4) volume = buffer.readFloat() pitch = buffer.readSoundPitch() diff --git a/src/main/resources/assets/minosoft/rendering/shader/includes/uv.glsl b/src/main/resources/assets/minosoft/rendering/shader/includes/uv.glsl index 211f9353d..345208cbc 100644 --- a/src/main/resources/assets/minosoft/rendering/shader/includes/uv.glsl +++ b/src/main/resources/assets/minosoft/rendering/shader/includes/uv.glsl @@ -1,6 +1,6 @@ -const vec2 CONST_UV[4] = vec2[4]( - vec2(+ 0.0f, + 1.0f), - vec2(+ 1.0f, + 0.0f), +const vec2 CONST_UV[4] = vec2[]( vec2(+ 0.0f, + 0.0f), - vec2(+ 1.0f, + 1.0f) + vec2(+ 0.0f, + 1.0f), + vec2(+ 1.0f, + 1.0f), + vec2(+ 1.0f, + 0.0f) ); diff --git a/src/main/resources/assets/minosoft/rendering/shader/world/border/border.vsh b/src/main/resources/assets/minosoft/rendering/shader/world/border/border.vsh index 0fb35a12d..61409d4b6 100644 --- a/src/main/resources/assets/minosoft/rendering/shader/world/border/border.vsh +++ b/src/main/resources/assets/minosoft/rendering/shader/world/border/border.vsh @@ -14,19 +14,21 @@ #version 330 core layout (location = 0) in vec3 vinPosition; -layout (location = 1) in float uvIndex; +layout (location = 1) in float vinUVIndex; +layout (location = 2) in float vinWidth; uniform mat4 uViewProjectionMatrix; uniform uint uIndexLayer; uniform float uTextureOffset; -uniform float uRadius; -uniform vec2 uCenter; -uniform float uCameraHeight; + +uniform vec3 uCameraPosition; flat out uint finTextureIndex; out vec3 finTextureCoordinates; -out vec3 finFragmentPosition; +out vec3 finFragmentPosition; // fog +#define DENSITY 2.0f +#define HEIGHT 150.0f #include "minosoft:uv" #include "minosoft:color" @@ -34,23 +36,22 @@ out vec3 finFragmentPosition; void main() { vec3 position = vinPosition; - position = position * uRadius; if (position.y < 0.0f) { - position.y = uCameraHeight - 300; + position.y = uCameraPosition.y - HEIGHT; } else if (position.y > 0.0f) { - position.y = uCameraHeight + 300; + position.y = uCameraPosition.y + HEIGHT; } - position.x += uCenter.x; - position.z += uCenter.y; gl_Position = uViewProjectionMatrix * vec4(position, 1.0f); - finFragmentPosition = position; finTextureIndex = uIndexLayer >> 28u; - vec2 uv = CONST_UV[floatBitsToUint(uvIndex)]; - uv.x *= (uRadius / 5.0f); - uv.y *= (300 / 5.0f); - finTextureCoordinates = vec3(uv, ((uIndexLayer >> 12) & 0xFFFFu)); + vec2 uv = CONST_UV[floatBitsToUint(vinUVIndex)]; + uv.x *= (vinWidth / DENSITY); // TODO: insert width + uv.y *= (HEIGHT / DENSITY); + + finTextureCoordinates = vec3(uv, ((uIndexLayer >> 12u) & 0xFFFFu)); finTextureCoordinates.x += uTextureOffset; finTextureCoordinates.y += uTextureOffset; + + finFragmentPosition = position.xyz; }