commonMain.ru.casperix.spine.animation.Curve.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of spine Show documentation
Show all versions of spine Show documentation
Signals for all occasions
The newest version!
package ru.casperix.spine.animation
import kotlinx.serialization.Serializable
import kotlinx.serialization.Transient
import ru.casperix.math.BezierCalculation
import ru.casperix.math.curve.float32.BezierCubic2f
import ru.casperix.math.vector.float32.Vector2f
import ru.casperix.misc.ceilToInt
import ru.casperix.spine.json.CurveSerializer
import kotlin.math.roundToInt
@Serializable(with = CurveSerializer::class)
interface Curve
@Serializable
object LinearCurve : Curve
@Serializable
object SteppedCurve : Curve
@Serializable
object UnknownCurve : Curve
@Serializable
class BezierCurve(val v1: Vector2f, val v2: Vector2f) : Curve {
companion object {
private val INITIAL_ERROR = 0.001f
private val STEPS = 128
}
@Transient
private var cache: BezierCurveCache? = null
fun getValue(lastFrame: ChannelFrame, nextFrame: ChannelFrame, currentTime: Float): Float {
getOrBuildCache(lastFrame, nextFrame).run {
val startTime = lastFrame.time
val finishTime = nextFrame.time
val pointIndex = ((STEPS - 1).toFloat() * (currentTime - startTime) / (finishTime - startTime)).ceilToInt().coerceIn(0..points.lastIndex)
val next = points[pointIndex]
return if (pointIndex == 0) {
next.y
} else {
val last = points[pointIndex - 1]
(currentTime - last.x) / (next.x - last.x) * (next.y - last.y) + last.y
}
}
}
private fun getOrBuildCache(lastFrame: ChannelFrame, nextFrame: ChannelFrame): BezierCurveCache {
if (cache == null) {
val curve = BezierCubic2f(
Vector2f(lastFrame.time, lastFrame.value),
v1,
v2,
Vector2f(nextFrame.time, nextFrame.value),
)
val startTime = lastFrame.time
val finishTime = nextFrame.time
val points = (0..STEPS).map { step ->
val t = step / STEPS.toFloat()
val time = startTime + t * (finishTime - startTime)
val value = BezierCalculation.getApproximateErrorHeightPrecision(curve, time, INITIAL_ERROR)
Vector2f(time, value)
}
cache = BezierCurveCache(
curve, points
)
}
return cache!!
}
class BezierCurveCache(val curve: BezierCubic2f, val points: List)
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy