commonMain.casperix.scene.camera.orbital.OrbitalCameraSmoother.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scene-camera Show documentation
Show all versions of scene-camera Show documentation
Camera control (regardless of the specific engine)
The newest version!
package casperix.scene.camera.orbital
import casperix.math.vector.asSpherical
import casperix.math.vector.float64.Vector2d
import casperix.math.vector.float64.Vector3d
import casperix.misc.DisposableHolder
import casperix.misc.clamp
import casperix.signals.concrete.Future
import casperix.signals.then
import kotlin.math.PI
class OrbitalCameraSmoother(val nextFrameFuture: Future, var frictionFactor: Double = 0.6, var elasticityFactor: Double = 0.6, val outputTransform: (state: OrbitalCameraState) -> Unit) : DisposableHolder() {
private var current: OrbitalCameraState? = null
private var finish: OrbitalCameraState? = null
private var offsetSpeed = Vector3d.ZERO
private var pivotSpeed = Vector2d.ZERO
init {
nextFrameFuture.then(components) {
update()
}
}
private fun update() {
val current = current ?: return
val finish = finish ?: return
val RVH = finish.offset.asVector3d() - current.offset.asVector3d()
val range = RVH.x
val vAngle = RVH.y
val hAngle = RVH.z
val deltaOffset = Vector3d(range, prepareAngleForInterpolate(vAngle), prepareAngleForInterpolate(hAngle))
val deltaPivot = finish.pivot - current.pivot
val elasticityFactor = elasticityFactor.clamp(0.0, 1.0)
val frictionFactor = frictionFactor.clamp(0.0, 1.0)
offsetSpeed += deltaOffset * elasticityFactor * (1.0 - frictionFactor) - offsetSpeed * elasticityFactor
pivotSpeed += deltaPivot * elasticityFactor * (1.0 - frictionFactor) - pivotSpeed * elasticityFactor
val next = OrbitalCameraState(current.pivot + pivotSpeed, (current.offset.asVector3d() + offsetSpeed).asSpherical())
this.current = next
outputTransform(next)
}
private fun prepareAngleForInterpolate(factor: Double): Double {
return (factor + 9.0 * PI) % (2.0 * PI) - PI
}
fun inputState(state: OrbitalCameraState) {
if (current == null) {
current = state
}
finish = state
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy