Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve camera shaking #15

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ class ShakingC(profile: RenderingProfile) {
*/
var enabled by BooleanDelegate(profile, true)

var amplifier by FloatDelegate(profile, 1.0f, "", ranges = arrayOf(0.1f..2.0f))
var speed by FloatDelegate(profile, 1.0f, "", ranges = arrayOf(0.1f..2.0f))
var intensity by FloatDelegate(profile, 1.0f, "", ranges = arrayOf(0.1f..2.0f))

/**
* Shake the camera while walking
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,14 @@ class MatrixHandler(
fun draw() {
dynamicFOV += camera.view.view.fovMultiplier

shaking.draw()
val shaking = shaking.update()
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 && matrixPosition == this.matrixPosition && front == this.front && fov == previousFOV && shaking.isEmpty) {
if (!shaking && upToDate && matrixPosition == this.matrixPosition && front == this.front && fov == previousFOV) {
return
}
this.matrixPosition = matrixPosition
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,44 +20,81 @@ import de.bixilon.kutil.avg.FloatAverage
import de.bixilon.kutil.time.TimeUtil.millis
import de.bixilon.minosoft.config.profile.profiles.rendering.camera.shaking.ShakingC
import de.bixilon.minosoft.gui.rendering.camera.Camera
import de.bixilon.minosoft.gui.rendering.renderer.drawable.Drawable
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import kotlin.math.sin

class CameraShaking(
private val camera: Camera,
private val profile: ShakingC,
) : Drawable {
private var rotation = 0.0f
private var strength = FloatAverage(5 * ProtocolDefinition.TICK_TIME * 1_000_000L, 1.0f)
) {
private var cameraTransform: Mat4? = Mat4()
private var damaged: Boolean = false
private val speed = FloatAverage(5 * ProtocolDefinition.TICK_TIME * 1_000_000L, 0.0f)
private val physics = camera.context.connection.camera.entity.physics

val isEmpty: Boolean get() = rotation == 0.0f

override fun draw() {
this.strength += 1.0f
val strength = this.strength.avg * profile.amplifier // strength affects how far it goes
fun update(): Boolean {
if (this.damaged) {
if (profile.damage) {
this.cameraTransform = updateDamage()
this.damaged = false
return true
}
}
if (profile.walking) {
this.cameraTransform = updateBobbing()
return true

val physics = camera.context.connection.camera.entity.physics
val velocity = physics.velocity.xz.length2().toFloat() // velocity affects how quick it goes
if (velocity > 0.003 && physics.onGround) {
this.speed += velocity
} else {
this.speed += 0.0f // TODO: remove this, kutil 1.21
}
val time = (millis() % 100L).toFloat() / 100.0f
return false
}

private fun updateBobbing(): Mat4? {
if (!this.physics.onGround) {
this.speed += 0.0f
return null
}
val transform = Mat4()
val time = millis()
this.speed += this.physics.velocity.xz.length2().toFloat() // velocity affects how quick it goes
val speed = minOf(this.speed.avg, 0.25f)
val translation = bobbing(time, speed, TRANSLATION_FREQUENCY * profile.speed, TRANSLATION_STRENGTH * profile.intensity)
val rotation = bobbing(time, speed, ROTATION_FREQUENCY * profile.speed, ROTATION_STRENGTH * profile.intensity)
transform.translateAssign(Vec3(0, translation, 0))
transform.rotateAssign(rotation, Vec3(0, 0, 1))
return transform
}

this.rotation = sin(time * minOf(this.speed.avg, 0.5f) / 3.0f) * strength * 0.03f
private fun bobbing(time: Long, speed: Float, frequency: Float, intensity: Float): Float {
val seconds = time / 1000.0

val sin = sin(seconds * frequency).toFloat()
return (sin * speed * intensity) / MINIMUM_SPEED
}

private fun updateDamage(): Mat4 {
val transform = Mat4()
val time = millis()
val rotation = bobbing(time, 0.5f, DAMAGE_FREQUENCY * profile.speed, DAMAGE_STRENGTH * profile.intensity)
transform.rotateAssign(rotation, Vec3(0, 0, 1))
return transform
}

fun onDamage() {
strength += 1000.0f
speed += 0.05f
this.damaged = true
}

fun transform(): Mat4? {
if (rotation == 0.0f) return null
return Mat4()
.rotateAssign(rotation, Vec3(0, 0, 1))
return cameraTransform
}

companion object {
private const val DAMAGE_FREQUENCY = 40.0f
private const val DAMAGE_STRENGTH = 0.004f
private const val ROTATION_STRENGTH = 0.002f
private const val ROTATION_FREQUENCY = 10.0f
private const val TRANSLATION_STRENGTH = 0.1f
private const val TRANSLATION_FREQUENCY = 15.0f
private const val MINIMUM_SPEED = 0.1f
}
}