Skip to content

Instantly share code, notes, and snippets.

@ylegall
Created August 28, 2020 21:47
Show Gist options
  • Save ylegall/c3b179987a464c043c963552a891052a to your computer and use it in GitHub Desktop.
Save ylegall/c3b179987a464c043c963552a891052a to your computer and use it in GitHub Desktop.
package org.ygl.openrndr.demos
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.color.mix
import org.openrndr.color.rgb
import org.openrndr.draw.LineCap
import org.openrndr.draw.LineJoin
import org.openrndr.extra.compositor.compose
import org.openrndr.extra.compositor.draw
import org.openrndr.extra.compositor.post
import org.openrndr.extra.fx.blur.GaussianBloom
import org.openrndr.extra.shapes.regularPolygon
import org.openrndr.extra.shapes.regularPolygonRounded
import org.openrndr.extra.shapes.regularStarRounded
import org.openrndr.ffmpeg.ScreenRecorder
import org.openrndr.math.Vector2
import org.openrndr.math.mix
import org.openrndr.math.smoothstep
import org.openrndr.math.transforms.transform
import org.openrndr.shape.Circle
import org.openrndr.shape.Rectangle
import org.openrndr.shape.ShapeContour
import org.ygl.kxa.ease.Ease
import kotlin.math.PI
import kotlin.math.cos
import kotlin.math.sin
private const val WIDTH = 920
private const val HEIGHT = 920
private const val TOTAL_FRAMES = 480
private const val LOOPS = 3
private const val RECORDING = true
fun main() = application {
configure {
width = WIDTH
height = HEIGHT
}
program {
var time = 0.0
val numPoints = 2000
val numLines = 12
val triangle = regularPolygonRounded(3, radius = 440.0)
val star = regularStarRounded(6, innerRadius = 200.0, outerRadius = 440.0, innerFactor = 0.5, outerFactor = 0.5)
val pentagon1 = regularPolygon(5, radius = 420.0)
val pentagon2 = regularPolygon(5, radius = 420.0, phase = 360.0 / 5)
//val line = Rectangle(Vector2(-width/2.0 + 100.0, 0.0), width - 200.0, 0.0).contour
//val line = Rectangle(Vector2(-width/2.0 + 100.0, 0.0), width - 200.0, 0.0).contour.transform(transform { rotate(degrees = 120.0) })
val rect = drawer.bounds.moved(-drawer.bounds.center).offsetEdges(-100.0).contour
val circle = Circle(Vector2.ZERO, 400.0).contour
val polar = (0 until numPoints).map { idx ->
val pct = idx / (numPoints - 0.0)
val angle = 2 * PI * (pct)
val mag1 = 200.0 + 150 * sin(3 * angle)
val p1 = Vector2(mag1 * cos(angle), mag1 * sin(angle))
p1
}.let { ShapeContour.fromPoints(it, false) }
val points = MutableList(numPoints) { Vector2.ZERO }
val shapeFunctions = listOf<(Double) -> Vector2>(
{ triangle.position(it) },
{ star.position(it) },
{ pentagon1.position(it) },
{ pentagon2.position(it) },
{ polar.position(it) },
{ rect.position(it) },
{ circle.position(1 - it) },
)
val colors = listOf(
rgb("FF616E"),
rgb("FFB672"),
rgb("fffd82"),
rgb("1efc1e"),
rgb("39FFC7"),
rgb("31afd4"),
rgb("D061FF"),
)
fun computeShape(timeOffset: Double) {
val adjustedTime = (1 + time - timeOffset) % 1.0
val currentIndex = (shapeFunctions.size * adjustedTime).toInt() % shapeFunctions.size
val nextIndex = (currentIndex + 1) % shapeFunctions.size
var t = (shapeFunctions.size * adjustedTime) % 1.0
t = smoothstep(0.1, 0.9, Ease.QUAD_INOUT(t))
val f1 = shapeFunctions[currentIndex]
val f2 = shapeFunctions[nextIndex]
for (i in 0 until numPoints) {
val pct = i / (numPoints - 1.0)
points[i] = mix(f1(pct), f2(pct), t)
}
}
val composite = compose {
draw {
drawer.translate(drawer.bounds.center)
drawer.clear(ColorRGBa.BLACK)
drawer.lineJoin = LineJoin.ROUND
drawer.lineCap = LineCap.ROUND
val adjustedTime = (1 + time) % 1.0
val currentIndex = (colors.size * adjustedTime).toInt() % colors.size
val nextIndex = (currentIndex + 1) % colors.size
var t = (colors.size * adjustedTime) % 1.0
t = smoothstep(0.1, 0.9, Ease.QUAD_INOUT(t))
val colorA = colors[currentIndex]
val colorB = colors[nextIndex]
val color = mix(colorA, colorB, t)
drawer.strokeWeight = 4.0
for (i in 0 until numLines) {
computeShape(i * 0.008)
val scale = 0.1 + (1 - i / (numLines - 1.0))
val scaledPoints = points.map { it * scale }
drawer.stroke = mix(color, ColorRGBa.WHITE, i / (numLines - 1.0))
drawer.contour(ShapeContour.fromPoints(scaledPoints, false))
}
}
post(GaussianBloom()) {
sigma = 0.1
}
}
if (RECORDING) {
extend(ScreenRecorder()) {
outputFile = "video/MorphingShapes.mp4"
frameRate = 60
frameClock = true
}
}
extend {
time = ((frameCount - 1) % TOTAL_FRAMES) / TOTAL_FRAMES.toDouble()
composite.draw(drawer)
if (RECORDING && frameCount >= TOTAL_FRAMES * LOOPS) {
application.exit()
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment