mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-15 18:34:56 -04:00
commit
f5fe58c1a4
@ -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")
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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
|
||||
}
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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?
|
||||
}
|
||||
}
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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
|
||||
}
|
@ -31,6 +31,7 @@ class Camera(
|
||||
|
||||
val view = ViewManager(this)
|
||||
|
||||
val offset = WorldOffset(this)
|
||||
|
||||
fun init() {
|
||||
matrixHandler.init()
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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 <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* 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
|
||||
}
|
||||
}
|
@ -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<Vec3>, val planes: Array<Vec4>)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -61,6 +61,8 @@ class EntityRenderer(
|
||||
var visibleCount: Int = 0
|
||||
private set
|
||||
|
||||
private var reset = false
|
||||
|
||||
override fun init(latch: CountUpAndDownLatch) {
|
||||
connection.events.listen<EntitySpawnEvent> { 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() {
|
||||
|
@ -23,4 +23,6 @@ interface ModelUpdater : Drawable {
|
||||
fun prepare() = Unit
|
||||
|
||||
fun unload() = Unit
|
||||
|
||||
fun reset() = Unit
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -47,6 +47,11 @@ abstract class EntityModel<E : Entity>(
|
||||
return update
|
||||
}
|
||||
|
||||
override fun reset() {
|
||||
update = true
|
||||
hitbox.reset()
|
||||
}
|
||||
|
||||
override fun prepareAsync() {
|
||||
if (!update) {
|
||||
return
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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 "")
|
||||
}
|
||||
|
@ -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.*
|
||||
|
||||
|
@ -20,5 +20,5 @@ import java.util.*
|
||||
|
||||
interface SingleBlockRenderable {
|
||||
|
||||
fun singleRender(position: Vec3i, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array<BlockState?>, light: ByteArray, tints: IntArray?): Boolean
|
||||
fun singleRender(position: Vec3i, offset: FloatArray, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array<BlockState?>, light: ByteArray, tints: IntArray?): Boolean
|
||||
}
|
||||
|
@ -32,10 +32,10 @@ class MultipartBakedModel(
|
||||
return sizes[direction.ordinal]
|
||||
}
|
||||
|
||||
override fun singleRender(position: Vec3i, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array<BlockState?>, light: ByteArray, tints: IntArray?): Boolean {
|
||||
override fun singleRender(position: Vec3i, offset: FloatArray, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array<BlockState?>, 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
|
||||
}
|
||||
}
|
||||
|
@ -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<BlockState?>, 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<BlockState?>, 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? {
|
||||
|
@ -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<BlockState?>, light: ByteArray, tints: IntArray?): Boolean {
|
||||
val floatPosition = position.toVec3()
|
||||
override fun singleRender(position: Vec3i, offset: FloatArray, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array<BlockState?>, light: ByteArray, tints: IntArray?): Boolean {
|
||||
val floatPosition = offset.toVec3()
|
||||
if (blockState.block is RandomOffsetBlock) {
|
||||
blockState.block.randomOffset?.let { floatPosition += position.getWorldOffset(it) }
|
||||
}
|
||||
|
@ -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())
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<CloudArray?>>()) {
|
||||
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
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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<PlaySoundEvent> { world.playSound(it.soundEvent, it.position, it.volume, it.pitch) },
|
||||
CallbackEventListener.of<ExplosionEvent> { world.playSound(ENTITY_GENERIC_EXPLODE, Vec3(it.position), 4.0f, (1.0f + (random.nextFloat() - random.nextFloat()) * 0.2f) * 0.7f) },
|
||||
CallbackEventListener.of<ExplosionEvent> { 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())
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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])
|
||||
}
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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<Vec2> {
|
||||
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<Vec2>, 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<Vec2>, 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)
|
||||
}
|
||||
|
@ -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<WorldBorderRenderer> {
|
||||
@ -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()
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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()
|
||||
}
|
||||
|
||||
|
@ -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<BlockState?>, light: ByteArray, tints: IntArray?): Boolean {
|
||||
override fun singleRender(position: Vec3i, offset: FloatArray, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array<BlockState?>, 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
|
||||
|
@ -38,7 +38,7 @@ class DoubleChestRenderer(
|
||||
light: Int,
|
||||
) : StorageBlockEntityRenderer<StorageBlockEntity>(
|
||||
blockState,
|
||||
SkeletalInstance(context, model, blockPosition.toVec3, (blockState.getFacing()).rotatedMatrix),
|
||||
SkeletalInstance(context, model, (blockPosition - context.camera.offset.offset).toVec3, (blockState.getFacing()).rotatedMatrix),
|
||||
light,
|
||||
) {
|
||||
|
||||
|
@ -38,7 +38,7 @@ class SingleChestRenderer(
|
||||
light: Int,
|
||||
) : StorageBlockEntityRenderer<StorageBlockEntity>(
|
||||
blockState,
|
||||
SkeletalInstance(context, model, blockPosition.toVec3, blockState.getFacing().rotatedMatrix),
|
||||
SkeletalInstance(context, model, (blockPosition - context.camera.offset.offset).toVec3, blockState.getFacing().rotatedMatrix),
|
||||
light,
|
||||
) {
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -76,15 +76,21 @@ class SolidCullSectionPreparer(
|
||||
val neighbourBlocks: Array<BlockState?> = 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) {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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)" }
|
||||
}
|
||||
}
|
||||
|
@ -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)" }
|
||||
}
|
||||
}
|
||||
|
@ -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)" }
|
||||
}
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
||||
|
@ -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)
|
||||
);
|
||||
|
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user