Skip to content

Instantly share code, notes, and snippets.

@ylegall
Created October 1, 2020 14:44
Show Gist options
  • Save ylegall/6b2682ffed6ee04696597003a7814e87 to your computer and use it in GitHub Desktop.
Save ylegall/6b2682ffed6ee04696597003a7814e87 to your computer and use it in GitHub Desktop.
Rhombille Spiral: code for https://www.instagram.com/p/CFpjO-1nBrp
package org.ygl.openrndr.demos
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.color.rgb
import org.openrndr.draw.renderTarget
import org.openrndr.extra.compositor.compose
import org.openrndr.extra.compositor.draw
import org.openrndr.extra.compositor.post
import org.openrndr.extra.fx.blur.FrameBlur
import org.openrndr.ffmpeg.VideoWriter
import org.openrndr.math.Polar
import org.openrndr.math.Vector2
import org.openrndr.math.mix
import org.openrndr.shape.Rectangle
import org.openrndr.shape.ShapeContour
import org.ygl.kxa.ease.Ease
import org.ygl.openrndr.demos.util.GlamourBlur
import org.ygl.openrndr.utils.isolatedWithTarget
private const val WIDTH = 920
private const val HEIGHT = 920
private const val TOTAL_FRAMES = 360
private const val LOOPS = 4
private const val DELAY_FRAMES = 60
private const val RECORDING = true
fun main() = application {
configure {
width = WIDTH
height = HEIGHT
}
program {
var time = 0.0
val rings = 48
val ringSegments = 18
val minRadius = 0.01
val maxRadius = 100.0
val scale = 200.0
val bgColor = rgb("14110f")
val fgColor1 = rgb("F2E8DE")
val fgColor2 = rgb("79746f")
val topShapes = mutableListOf<ShapeContour>()
val leftShapes = mutableListOf<ShapeContour>()
//val rightShapes = mutableListOf<ShapeContour>()
fun mobiusTransform(pos: Vector2): Vector2 {
val (x, y) = pos
val denom = (x + 1) * (x + 1) + y * y
return Vector2((x * x - 1 + y * y) / denom, 2 * y / denom)
}
fun getPoint(angle: Double, radius: Double): Vector2 {
val normalizedRadius = ((radius + 2 * time) / (rings - 1.0))
val normalizedAngle = 360.0 * (angle + 2 * time) / (ringSegments - 0.0)
val rad = mix(minRadius, maxRadius, Ease.CUBE_IN(normalizedRadius))
return mobiusTransform(Vector2.fromPolar(Polar(normalizedAngle, rad)))
}
fun update() {
topShapes.clear()
leftShapes.clear()
//rightShapes.clear()
(0 until rings).forEach { r ->
val angleOffset = if (r % 2 == 0) 0.5 else 0.0
(0 until ringSegments).forEach { i ->
val angle = angleOffset + i
topShapes.add(ShapeContour.fromPoints(listOf(
getPoint(angle + 0.0, r + 0.0),
getPoint(angle + 0.5, r + 0.333),
getPoint(angle + 0.0, r + 0.666),
getPoint(angle - 0.5, r + 0.333),
), true))
leftShapes.add(ShapeContour.fromPoints(listOf(
getPoint(angle + 0.0, r + 0.0),
getPoint(angle - 0.5, r + 0.333),
getPoint(angle - 0.5, r - 0.333),
getPoint(angle + 0.0, r - 0.666),
), true))
//rightShapes.add(ShapeContour.fromPoints(listOf(
// getPoint(angle + 0.0, r + 0.0),
// getPoint(angle + 0.0, r - 0.666),
// getPoint(angle + 0.5, r - 0.333),
// getPoint(angle + 0.5, r + 0.333),
//), true))
}
}
}
fun filterShapes(contours: List<ShapeContour>) = contours.filter { contour ->
contour.segments.all {
it.start.x in -10.0..10.0 &&
it.start.y in -10.0..10.0 &&
it.end.x in -10.0..10.0 &&
it.end.y in -10.0..10.0
}
}
val composite = compose {
draw {
drawer.translate(drawer.bounds.center)
drawer.scale(scale)
drawer.clear(bgColor)
drawer.stroke = null
drawer.fill = fgColor1
drawer.contours(filterShapes(topShapes))
drawer.fill = fgColor2
drawer.contours(filterShapes(leftShapes))
//drawer.fill = ColorRGBa.BLACK
//drawer.contours(rightShapes)
}
post(GlamourBlur())
post(FrameBlur())
}
val videoTarget = renderTarget(width, height) { colorBuffer() }
val videoWriter = VideoWriter.create()
.size(width, height)
.frameRate(60)
.output("video/DoyleCubes-long.mp4")
if (RECORDING) {
videoWriter.start()
}
extend {
time = ((frameCount - 1) % TOTAL_FRAMES) / TOTAL_FRAMES.toDouble()
update()
if (RECORDING) {
drawer.isolatedWithTarget(videoTarget) {
composite.draw(this)
}
drawer.image(videoTarget.colorBuffer(0))
if (frameCount > DELAY_FRAMES) {
videoWriter.frame(videoTarget.colorBuffer(0))
}
if (frameCount >= TOTAL_FRAMES * LOOPS + DELAY_FRAMES) {
videoWriter.stop()
application.exit()
}
} else {
composite.draw(drawer)
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment