diff --git a/orx-easing/build.gradle b/orx-easing/build.gradle new file mode 100644 index 00000000..d3bbc651 --- /dev/null +++ b/orx-easing/build.gradle @@ -0,0 +1,20 @@ +sourceSets { + demo { + java { + srcDirs = ["src/demo/kotlin"] + compileClasspath += main.getCompileClasspath() + runtimeClasspath += main.getRuntimeClasspath() + } + } +} + +dependencies { + implementation project(":orx-shader-phrases") + implementation project(":orx-parameters") + + demoImplementation(project(":orx-camera")) + demoImplementation("org.openrndr:openrndr-core:$openrndrVersion") + demoRuntimeOnly("org.openrndr:openrndr-gl3:$openrndrVersion") + demoRuntimeOnly("org.openrndr:openrndr-gl3-natives-$openrndrOS:$openrndrVersion") + demoImplementation(sourceSets.getByName("main").output) +} \ No newline at end of file diff --git a/orx-easing/src/demo/kotlin/DemoEasings01.kt b/orx-easing/src/demo/kotlin/DemoEasings01.kt new file mode 100644 index 00000000..ce0eb282 --- /dev/null +++ b/orx-easing/src/demo/kotlin/DemoEasings01.kt @@ -0,0 +1,82 @@ +import org.openrndr.application +import org.openrndr.color.ColorRGBa +import org.openrndr.extras.easing.* +import org.openrndr.math.Vector2 + +fun main() { + application { + + configure { + width = 1280 + height = 1080 + } + program { + fun drawEasing(f: EasingFunction) { + drawer.stroke = ColorRGBa.PINK + val points = mutableListOf() + for (i in 0 .. 40) { + val y = 40.0 - f(i / 40.0, 0.0, 1.0, 1.0) * 40.0 + points.add(Vector2(i*10.0, y)) + } + drawer.lineStrip(points) + + drawer.stroke = ColorRGBa.GRAY + drawer.lineSegment(0.0, 40.0, 400.0, 40.0) + + + drawer.lineSegment(0.0, 20.0, 400.0, 20.0) + + } + extend { + drawer.stroke = ColorRGBa.WHITE + + val functions = listOf( + ::easeLinear, + ::easeQuadIn, + ::easeQuadOut, + ::easeQuadInOut, + ::easeCubicIn, + ::easeCubicOut, + ::easeCubicInOut, + ::easeCircIn, + ::easeCircOut, + ::easeCircInOut, + ::easeQuartIn, + ::easeQuartOut, + ::easeQuartInOut, + ::easeExpoIn, + ::easeExpoOut, + ::easeExpoInOut, + ::easeQuintIn, + ::easeQuintOut, + ::easeQuintInOut, + ::easeSineIn, + ::easeSineOut, + ::easeSineInOut, + ::easeBackIn, + ::easeBackOut, + ::easeBackInOut, + ::easeElasticIn, + ::easeElasticOut, + ::easeElasticInOut, + ::easeBounceIn, + ::easeBounceOut, + ::easeBounceInOut + + ) + + var i = 0 + for (f in functions) { + drawEasing(f) + drawer.translate(0.0, 50.0) + i ++ + if (i > 19) { + drawer.translate(450.0, -20 * 50.0) + i = 0 + } + } + } + } + } + +} \ No newline at end of file diff --git a/orx-easing/src/main/kotlin/Easing.kt b/orx-easing/src/main/kotlin/Easing.kt index a855032f..d37a7dd5 100644 --- a/orx-easing/src/main/kotlin/Easing.kt +++ b/orx-easing/src/main/kotlin/Easing.kt @@ -1,5 +1,10 @@ package org.openrndr.extras.easing +import kotlin.math.cos +import kotlin.math.pow +import kotlin.math.sin +import kotlin.math.sqrt + typealias EasingFunction = (Double, Double, Double, Double) -> Double fun easeLinear(t: Double, b: Double = 0.0, c: Double = 1.0, d: Double = 1.0) = c * (t / d) + b @@ -7,7 +12,7 @@ fun easeLinear(t: Double, b: Double = 0.0, c: Double = 1.0, d: Double = 1.0) = c // -- constant fun easeZero(t: Double, b: Double = 0.0, c: Double = 1.0, d: Double = 1.0) = b -fun easeOne(t: Double, b: Double = 0.0, c: Double = 1.0, d : Double = 1.0) = b + c +fun easeOne(t: Double, b: Double = 0.0, c: Double = 1.0, d: Double = 1.0) = b + c // -- back @@ -22,13 +27,17 @@ fun easeBackInOut(t: Double, b: Double = 0.0, c: Double = 1.0, d: Double = 1.0): val s2 = s * 1.525 val td2 = t / (d / 2) val td22 = td2 - 2 - return if (td2 < 1) c / 2 * (t * t * ((s + 1) * t - s)) + b else c / 2 * ((td22) * td22 * (((s2) + 1) * t + s2) + 2) + b + return if (td2 < 1) { + c / 2 * (td2 * td2 * ((s + 1) * td2 - s)) + b + } else { + c / 2 * ((td22) * td22 * (((s2) + 1) * td22 + s2) + 2) + b + } } fun easeBackOut(t: Double, b: Double = 0.0, c: Double = 1.0, d: Double = 1.0): Double { val s = 1.70158 val td1 = t / d - 1 - return c * (td1 * td1 * ((s + 1) * t + s) + 1) + b + return c * (td1 * td1 * ((s + 1) * td1 + s) + 1) + b } // -- bounce @@ -39,15 +48,15 @@ fun easeBounceIn(t: Double, b: Double = 0.0, c: Double = 1.0, d: Double = 1.0): t1 /= d if (t1 < 1 / 2.75) { result = c * (7.5625 * t1 * t1) + 0.toDouble() - } else if (t1 < 2 / 2.75f) { + } else if (t1 < 2 / 2.75) { t1 -= (1.5 / 2.75) - result = c * (7.5625 * (t1 * t1 + .75f)) + result = c * (7.5625 * (t1) * t1 + .75) } else if (t1 < 2.5 / 2.75) { t1 -= 2.25 / 2.75 - result = c * (7.5625 * (t1 * t1 + .9375f)) + result = c * (7.5625 * (t1) * t1 + .9375) } else { t1 -= (2.625 / 2.75) - result = c * (7.5625 * (t1) * t1 + .984375f) + result = c * (7.5625 * (t1) * t1 + .984375) } return c - result + b } @@ -56,32 +65,32 @@ fun easeBounceInOut(t: Double, b: Double = 0.0, c: Double = 1.0, d: Double = 1.0 var t1 = d - t * 2 val result: Double t1 /= d - if (t1 < 1 / 2.75f) { + if (t1 < 1 / 2.75) { result = c * (7.5625 * t1 * t1) + 0.toDouble() - } else if (t1 < 2 / 2.75f) { + } else if (t1 < 2 / 2.75) { t1 -= 1.5 / 2.75 - result = c * (7.5625 * (t1) * t1 + .75f) + 0.toDouble() + result = c * (7.5625 * (t1) * t1 + .75) + 0.toDouble() } else if (t1 < 2.5 / 2.75) { t1 -= 2.25 / 2.75 - result = c * (7.5625 * (t1) * t1 + .9375f) + 0.toDouble() + result = c * (7.5625 * (t1) * t1 + .9375) + 0.toDouble() } else { t1 -= 2.625 / 2.75 - result = c * (7.5625 * (t1) * t1 + .984375f) + 0.toDouble() + result = c * (7.5625 * (t1) * t1 + .984375) + 0.toDouble() //return c * (7.5625 * pow((t/d) -(2.625 / 2.75),2) + .984375) + b; } var t2 = t * 2 - d val result1: Double t2 /= d - if (t2 < 1 / 2.75f) result1 = c * (7.5625 * t2 * t2) + 0.toDouble() else if (t2 < 2 / 2.75f) { + if (t2 < 1 / 2.75) result1 = c * (7.5625 * t2 * t2) + 0.toDouble() else if (t2 < 2 / 2.75) { t2 -= 1.5 / 2.75 - result1 = c * (7.5625 * t2 * t2 + .75f) + result1 = c * (7.5625 * t2 * t2 + .75) } else if (t2 < 2.5 / 2.75) { t2 -= 2.25 / 2.75 - result1 = c * (7.5625 * t2 * t2 + .9375f) + result1 = c * (7.5625 * t2 * t2 + .9375) } else { t2 -= 2.626 / 2.75 - result1 = c * (7.5625 * t2 * t2 + .984375f) + result1 = c * (7.5625 * t2 * t2 + .984375) } return if (t < d / 2) (c - result) * .5 + b @@ -94,17 +103,17 @@ fun easeBounceOut(t: Double, b: Double = 0.0, c: Double = 1.0, d: Double = 1.0): var td = t / d - return if (td < (1 / 2.75f)) { - c * (7.5625f * td * td) + b - } else if (t < (2 / 2.75f)) { + return if (td < (1 / 2.75)) { + c * (7.5625 * td * td) + b + } else if (t < (2 / 2.75)) { td -= 1.5 / 2.75 - c * (7.5625f * td * td + .75f) + b + c * (7.5625 * td * td + .75) + b } else if (t < (2.5 / 2.75)) { td -= 2.25 / 2.75 - c * (7.5625f * td * td + .9375f) + b + c * (7.5625 * td * td + .9375) + b } else { td -= 2.625 / 2.75 - c * (7.5625f * td * td + .984375f) + b + c * (7.5625 * td * td + .984375) + b } } @@ -112,20 +121,20 @@ fun easeBounceOut(t: Double, b: Double = 0.0, c: Double = 1.0, d: Double = 1.0): fun easeCircIn(t: Double, b: Double = 0.0, c: Double = 1.0, d: Double = 1.0): Double { val td = t / d - return -c * (Math.sqrt(1 - td * td) - 1) + b + return -c * (sqrt(1 - td * td) - 1) + b } fun easeCircInOut(t: Double, b: Double = 0.0, c: Double = 1.0, d: Double = 1.0): Double { var td2 = t / (d / 2.0) if (td2 < 1) - return -c / 2 * (Math.sqrt(1 - td2 * td2) - 1) + b + return -c / 2 * (sqrt(1 - td2 * td2) - 1) + b td2 -= 2 - return c / 2 * (Math.sqrt(1 - td2 * td2) + 1) + b + return c / 2 * (sqrt(1 - td2 * td2) + 1) + b } fun easeCircOut(t: Double, b: Double, c: Double, d: Double): Double { val td = t / d - 1 - return c * Math.sqrt(1 - td * td) + b + return c * sqrt(1 - td * td) + b } // -- cubic @@ -155,25 +164,28 @@ fun easeElasticIn(t: Double, b: Double, c: Double, d: Double): Double { return b + c } else { var td = t / d - val p = d * .3f + val p = d * .3 val s = p / 4 td -= 1.0 - return -(c * Math.pow(2.0, 10 * (td)) * Math.sin((td * d - s) * (2 * Math.PI) / p)) + b + return -(c * 2.0.pow(10 * (td)) * sin((td * d - s) * (2 * Math.PI) / p)) + b } } fun easeElasticInOut(t: Double, b: Double, c: Double, d: Double): Double { - var td2 = t / (d / 2) + val td2 = t / (d / 2) if (t == 0.0) return b if (td2 == 2.0) return b + c - val p = d * (.3f * 1.5f) + val p = d * (.3 * 1.5) val s = p / 4 - td2 -= 1.0 val td3 = td2 - 1.0 - return if (t < 1) -.5f * (c * Math.pow(2.0, 10 * (td2)) * Math.sin((td2 * d - s) * (2 * Math.PI) / p)) + b else c * Math.pow(2.0, -10 * (td3) * Math.sin(td3 * d - s) * (2 * Math.PI) / p) * .5f + c + b + return if (td2 < 1) { + -.5 * (c * 2.0.pow(10 * (td3)) * sin((td3 - s) * (2 * Math.PI) / p)) + b + } else { + c * 2.0.pow(-10 * (td3) * sin(td3 - s) * (2 * Math.PI) / p) * .5 + c + b + } } @@ -183,31 +195,33 @@ fun easeElasticOut(t: Double, b: Double, c: Double, d: Double): Double { return b if (td == 1.0) return b + c - val p = d * .3f + val p = d * .3 val s = p / 4 - return c * Math.pow(2.0, -10 * td) * Math.sin((td * d - s) * (2 * Math.PI) / p) + c + b + return c * 2.0.pow(-10 * td) * sin((td * d - s) * (2 * Math.PI) / p) + c + b } // -- expo fun easeExpoIn(t: Double, b: Double = 0.0, c: Double = 1.0, d: Double = 1.0): Double = - if (t == 0.0) b else c * Math.pow(2.0, 10 * (t / d - 1)) + b + if (t == 0.0) b else c * 2.0.pow(10 * (t / d - 1)) + b fun easeExpoInOut(t: Double, b: Double = 0.0, c: Double = 1.0, d: Double = 1.0): Double { val td2 = t / (d / 2) + val t2 = t * 2 return if (t == 0.0) { b } else if (t == d) { b + c - } else if (td2 < 1) { - c / 2 * Math.pow(2.0, 10 * (t - 1)) + b + } else if (t < d / 2) { + (c / 2) * 2.0.pow(10 * (t2 - 1)) + b } else { - c / 2 * (-Math.pow(2.0, -10 * (t - 1.0)) + 2) + b + + (c / 2) * (-(2.0.pow(-10 * (t2 - 1.0))) + 2) + b } } fun easeExpoOut(t: Double, b: Double = 0.0, c: Double = 1.0, d: Double = 1.0): Double = - if (t == d) b + c else c * (-Math.pow(2.0, -10 * t / d) + 1) + b + if (t == d) b + c else c * (-(2.0.pow(-10 * t / d)) + 1) + b // -- quad @@ -250,8 +264,11 @@ fun easeQuintIn(t: Double, b: Double, c: Double, d: Double): Double { } fun easeQuintInOut(t: Double, b: Double, c: Double, d: Double): Double { - val td = t / d - return c * td * td * td * td * td + b + val t2 = t * 2.0 + val t22 = t2 - 2.0 + return if (t < 0.5) 0.5 * t2 * t2 * t2 * t2 * t2 else { + 0.5 * (t22 * t22 * t22 * t22 * t22 + 2.0) + } } fun easeQuintOut(t: Double, b: Double, c: Double, d: Double): Double { @@ -262,13 +279,13 @@ fun easeQuintOut(t: Double, b: Double, c: Double, d: Double): Double { // -- sine fun easeSineIn(t: Double, b: Double = 0.0, c: Double = 1.0, d: Double = 1.0): Double = - -c * Math.cos(t / d * (Math.PI / 2)) + c + b + -c * cos(t / d * (Math.PI / 2)) + c + b fun easeSineOut(t: Double, b: Double = 0.0, c: Double = 1.0, d: Double = 1.0): Double = - c * Math.sin(t / d * (Math.PI / 2)) + b + c * sin(t / d * (Math.PI / 2)) + b fun easeSineInOut(t: Double, b: Double, c: Double, d: Double): Double = - -c / 2 * (Math.cos(Math.PI * t / d) - 1) + b + -c / 2 * (cos(Math.PI * t / d) - 1) + b enum class Easing(val function: EasingFunction) {