package org.openrndr.extra.keyframer import org.openrndr.extra.easing.Easing import org.openrndr.extra.easing.EasingFunction import org.openrndr.math.Quaternion import org.openrndr.math.slerp class KeyQuaternion(val time: Double, val value: Quaternion, val easing: EasingFunction) class KeyframerChannelQuaternion { val keys = mutableListOf() operator fun invoke() : Double { return 0.0 } fun add(time: Double, value: Quaternion?, easing: EasingFunction = Easing.Linear.function) { value?.let { keys.add(KeyQuaternion(time, it, easing)) } } fun lastValue(): Quaternion? { return keys.lastOrNull()?.value } fun duration(): Double { return keys.last().time } fun value(time: Double): Quaternion? { if (keys.size == 0) { return null } if (keys.size == 1) { return if (time < keys.first().time) { keys[0].value.normalized } else { keys[0].value.normalized } } if (time < keys.first().time) { return null } val rightIndex = keys.indexOfFirst { it.time > time } return if (rightIndex == -1) { keys.last().value.normalized } else { val leftIndex = (rightIndex - 1).coerceAtLeast(0) val rightKey = keys[rightIndex] val leftKey = keys[leftIndex] val t0 = (time - leftKey.time) / (rightKey.time - leftKey.time) val e0 = rightKey.easing(t0, 0.0, 1.0, 1.0) slerp(leftKey.value, rightKey.value, e0).normalized } } }