Demos: ensure all use fun main() = application {

- Adjust some demo window sizes.
- Replace Random.double by Double.uniform
- Tweak some demos so screenshots look more interesting
This commit is contained in:
Abe Pazos
2025-01-26 20:57:04 +01:00
parent 1975a820fc
commit c8f7dd52c6
116 changed files with 2889 additions and 2942 deletions

View File

@@ -4,41 +4,39 @@ import org.openrndr.draw.isolated
import org.openrndr.shape.Circle
import org.openrndr.shape.Rectangle
fun main() {
application {
configure {
width = 720
height = 720
}
fun main() = application {
configure {
width = 720
height = 720
}
program {
val cs = Rectangle(0.0, 0.0, 200.0, 200.0).contour
val cc = Circle(100.0, 0.0, 100.0).contour
program {
val cs = Rectangle(0.0, 0.0, 200.0, 200.0).contour
val cc = Circle(100.0, 0.0, 100.0).contour
extend {
drawer.fill = ColorRGBa.GRAY
drawer.stroke = ColorRGBa.PINK
drawer.isolated {
drawer.contour(cs)
drawer.translate(300.0, 0.0)
extend {
drawer.fill = ColorRGBa.GRAY
drawer.stroke = ColorRGBa.PINK
drawer.isolated {
drawer.contour(cs)
drawer.translate(300.0, 0.0)
// this should create a contour similar to the input contour
drawer.contour(cs.sampleEquidistant(4))
drawer.contour(cs.sampleEquidistant(3))
}
// this should create a contour similar to the input contour
drawer.contour(cs.sampleEquidistant(4))
drawer.contour(cs.sampleEquidistant(3))
}
drawer.isolated {
drawer.translate(.0, 400.0)
drawer.contour(cc)
drawer.translate(300.0, 0.0)
drawer.isolated {
drawer.translate(.0, 400.0)
drawer.contour(cc)
drawer.translate(300.0, 0.0)
drawer.contour(cc)
// this should draw a hexagon
drawer.contour(cc.sampleEquidistant(6))
// this should draw a triangle
drawer.contour(cc.sampleEquidistant(3))
}
drawer.contour(cc)
// this should draw a hexagon
drawer.contour(cc.sampleEquidistant(6))
// this should draw a triangle
drawer.contour(cc.sampleEquidistant(3))
}
}
}
}
}

View File

@@ -13,42 +13,40 @@ import org.openrndr.shape.Triangle
* a 3x3 grid of triangles and lines.
*/
fun main() {
application {
configure {
width = 720
height = 720
}
fun main() = application {
configure {
width = 720
height = 720
}
program {
val font = loadFont("demo-data/fonts/IBMPlexMono-Regular.ttf", 20.0)
val pointA = Vector2(0.0, 50.0)
val pointB = Vector2(50.0, -20.0)
val pointC = Vector2(-50.0, 0.0)
val triangle = Triangle(pointA, pointB, pointC).contour
program {
val font = loadFont("demo-data/fonts/IBMPlexMono-Regular.ttf", 20.0)
val pointA = Vector2(0.0, 50.0)
val pointB = Vector2(50.0, -20.0)
val pointC = Vector2(-50.0, 0.0)
val triangle = Triangle(pointA, pointB, pointC).contour
extend {
drawer.apply {
fill = ColorRGBa.GRAY
stroke = ColorRGBa.PINK
strokeWeight = 8.0
fontMap = font
LineCap.entries.forEachIndexed { x, cap ->
lineCap = cap
LineJoin.entries.forEachIndexed { y, join ->
lineJoin = join
val pos = IntVector2(x - 1, y - 1).vector2 * 180.0
isolated {
translate(bounds.position(0.46, 0.46) + pos)
text("cap: ${cap.name}", -30.5, 80.5)
text("join: ${join.name}", -30.5, 100.5)
contour(triangle)
lineSegment(pointA - pointC, pointB - pointC)
}
extend {
drawer.apply {
fill = ColorRGBa.GRAY
stroke = ColorRGBa.PINK
strokeWeight = 8.0
fontMap = font
LineCap.entries.forEachIndexed { x, cap ->
lineCap = cap
LineJoin.entries.forEachIndexed { y, join ->
lineJoin = join
val pos = IntVector2(x - 1, y - 1).vector2 * 180.0
isolated {
translate(bounds.position(0.46, 0.46) + pos)
text("cap: ${cap.name}", -30.5, 80.5)
text("join: ${join.name}", -30.5, 100.5)
contour(triangle)
lineSegment(pointA - pointC, pointB - pointC)
}
}
}
}
}
}
}
}

View File

@@ -2,41 +2,37 @@ import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extra.composition.composition
import org.openrndr.extra.composition.drawComposition
import org.openrndr.extra.svg.saveToFile
import org.openrndr.extra.svg.toSVG
import org.openrndr.math.Vector2
import java.io.File
fun main() {
application {
program {
val composition = drawComposition {
val layer = group {
fill = ColorRGBa.PINK
stroke = ColorRGBa.BLACK
strokeWeight = 10.0
circle(Vector2(width / 2.0, height / 2.0), 100.0)
circle(Vector2(200.0, 200.0), 50.0)
}
// demonstrating how to set custom attributes on the CompositionNode
// these are stored in SVG
//layer.id = "Layer_2"
//layer.attributes["inkscape:label"] = "Layer 1"
//layer.attributes["inkscape:groupmode"] = "layer"
fun main() = application {
program {
val composition = drawComposition {
val layer = group {
fill = ColorRGBa.PINK
stroke = ColorRGBa.BLACK
strokeWeight = 10.0
circle(Vector2(width / 2.0, height / 2.0), 100.0)
circle(Vector2(200.0, 200.0), 50.0)
}
// demonstrating how to set custom attributes on the CompositionNode
// these are stored in SVG
//layer.id = "Layer_2"
//layer.attributes["inkscape:label"] = "Layer 1"
//layer.attributes["inkscape:groupmode"] = "layer"
}
// print the svg to the console
println(composition.toSVG())
// print the svg to the console
println(composition.toSVG())
// save svg to a File
//composition.saveToFile(File("/path/to/design.svg"))
// save svg to a File
//composition.saveToFile(File("/path/to/design.svg"))
extend {
drawer.clear(ColorRGBa.WHITE)
extend {
drawer.clear(ColorRGBa.WHITE)
// draw the composition to the screen
drawer.composition(composition)
}
// draw the composition to the screen
drawer.composition(composition)
}
}
}
}

View File

@@ -4,23 +4,21 @@ import org.openrndr.extra.composition.ClipMode
import org.openrndr.extra.composition.composition
import org.openrndr.extra.composition.drawComposition
fun main() {
application {
program {
val cd = drawComposition {
fill = null
circle(width / 2.0, height / 2.0, 100.0)
fun main() = application {
program {
val cd = drawComposition {
fill = null
circle(width / 2.0, height / 2.0, 100.0)
fill = ColorRGBa.BLACK
clipMode = ClipMode.REVERSE_DIFFERENCE
circle(width / 2.0 + 50.0, height / 2.0, 100.0)
}
fill = ColorRGBa.BLACK
clipMode = ClipMode.REVERSE_DIFFERENCE
circle(width / 2.0 + 50.0, height / 2.0, 100.0)
}
extend {
drawer.clear(ColorRGBa.PINK)
drawer.composition(cd)
}
extend {
drawer.clear(ColorRGBa.PINK)
drawer.composition(cd)
}
}
}
}

View File

@@ -4,25 +4,22 @@ import org.openrndr.extra.composition.ClipMode
import org.openrndr.extra.composition.composition
import org.openrndr.extra.composition.drawComposition
fun main() {
application {
program {
val cd = drawComposition {
fill = null
clipMode = ClipMode.REVERSE_DIFFERENCE
fun main() = application {
program {
val cd = drawComposition {
fill = null
clipMode = ClipMode.REVERSE_DIFFERENCE
circle(width / 2.0-50.0, height / 2.0, 100.0)
circle(width / 2.0+50.0, height / 2.0, 100.0)
circle(width / 2.0 - 50.0, height / 2.0, 100.0)
circle(width / 2.0 + 50.0, height / 2.0, 100.0)
fill = ColorRGBa.BLACK
circle(width / 2.0, height / 2.0, 100.0)
}
fill = ColorRGBa.BLACK
circle(width / 2.0, height / 2.0, 100.0)
}
extend {
drawer.clear(ColorRGBa.PINK)
drawer.composition(cd)
}
extend {
drawer.clear(ColorRGBa.PINK)
drawer.composition(cd)
}
}
}
}

View File

@@ -201,38 +201,36 @@ import org.openrndr.extra.fx.edges.EdgesWork
import org.openrndr.extra.gui.GUI
import org.openrndr.math.Vector2
fun main() {
application {
configure {
width = 768
height = 768
}
program {
val w2 = width / 2.0
val h2 = height / 2.0
fun main() = application {
configure {
width = 768
height = 768
}
program {
val w2 = width / 2.0
val h2 = height / 2.0
val c = compose {
draw {
drawer.fill = ColorRGBa.PINK
drawer.circle(width / 2.0, height / 2.0, 10.0)
}
layer {
blend(Add())
val c = compose {
draw {
drawer.fill = ColorRGBa.PINK
drawer.circle(width / 2.0, height / 2.0, 10.0)
drawer.circle(width / 2.0, height / 2.0, 100.0)
}
layer {
blend(Add())
draw {
drawer.circle(width / 2.0, height / 2.0, 100.0)
}
post(ApproximateGaussianBlur()) {
window = 10
sigma = Math.cos(seconds * 10.0) * 10.0 + 10.0
}
post(ApproximateGaussianBlur()) {
window = 10
sigma = Math.cos(seconds * 10.0) * 10.0 + 10.0
}
}
extend(gui)
extend {
c.draw(drawer)
}
}
extend(gui)
extend {
c.draw(drawer)
}
}
}

View File

@@ -6,29 +6,31 @@ import org.openrndr.extra.fx.blur.HashBlurDynamic
import org.openrndr.extra.fx.patterns.Checkers
import kotlin.math.cos
fun main() {
application {
program {
val c = compose {
layer {
val a = aside(colorType = ColorType.FLOAT32) {
post(Checkers()) {
this.size = cos(seconds)*0.5 + 0.5
}
}
draw {
drawer.clear(ColorRGBa.GRAY.shade(0.5))
drawer.circle(width/2.0, height/2.0, 100.0)
}
post(HashBlurDynamic(), a) {
time = seconds
radius = 25.0
fun main() = application {
configure {
width = 720
height = 720
}
program {
val c = compose {
layer {
val a = aside(colorType = ColorType.FLOAT32) {
post(Checkers()) {
this.size = cos(seconds + 2.0) * 0.5 + 0.5
}
}
}
extend {
c.draw(drawer)
draw {
drawer.clear(ColorRGBa.GRAY.shade(0.5))
drawer.circle(width / 2.0, height / 2.0, 100.0)
}
post(HashBlurDynamic(), a) {
time = seconds
radius = 25.0
}
}
}
extend {
c.draw(drawer)
}
}
}
}

View File

@@ -17,8 +17,8 @@ import kotlin.random.Random
*/
fun main() = application {
configure {
width = 900
height = 900
width = 720
height = 720
}
program {

View File

@@ -14,10 +14,9 @@ import org.openrndr.shape.Rectangle
* Try changing which layer has multisampling applied and observe the results.
*/
fun main() = application {
System.setProperty("org.openrndr.gl3.debug", "true")
configure {
width = 800
height = 800
width = 720
height = 720
}
program {
@@ -25,17 +24,17 @@ fun main() = application {
layer(multisample = BufferMultisample.SampleCount(4)) {
draw {
drawer.translate(drawer.bounds.center)
drawer.rotate(seconds)
drawer.rotate(seconds + 5)
drawer.fill = ColorRGBa.PINK
drawer.rectangle(Rectangle.fromCenter(Vector2.ZERO, 200.0))
}
layer {
layer() {
blend(Normal()) {
clip = true
}
draw {
drawer.rotate(seconds * -2)
drawer.rotate((seconds + 5) * -2)
drawer.fill = ColorRGBa.WHITE
drawer.rectangle(Rectangle.fromCenter(Vector2.ZERO, 200.0))
}

View File

@@ -8,33 +8,31 @@ import org.openrndr.extra.gui.GUI
import org.openrndr.extra.parameters.DoubleParameter
import org.openrndr.math.Vector2
fun main() {
application {
program {
val gui = GUI()
fun main() = application {
program {
val gui = GUI()
val state = object {
@DoubleParameter("radius", 0.0, 200.0)
var radius = 100.0
val state = object {
@DoubleParameter("radius", 0.0, 200.0)
var radius = 100.0
val difference by differencing(::radius)
val differenceHistory by tracking(::difference)
val differenceMax by aggregating(::differenceHistory) {
it.maxMag()
}
}
gui.add(state, "state")
extend(gui)
extend {
drawer.circle(drawer.bounds.center, state.radius)
drawer.stroke = ColorRGBa.GREEN
drawer.lineSegment(drawer.bounds.center, drawer.bounds.center + Vector2(state.difference, 0.0))
drawer.translate(0.0, 4.0)
drawer.stroke = ColorRGBa.BLUE
drawer.lineSegment(drawer.bounds.center, drawer.bounds.center + Vector2(state.differenceMax, 0.0))
val difference by differencing(::radius)
val differenceHistory by tracking(::difference)
val differenceMax by aggregating(::differenceHistory) {
it.maxMag()
}
}
gui.add(state, "state")
extend(gui)
extend {
drawer.circle(drawer.bounds.center, state.radius)
drawer.stroke = ColorRGBa.GREEN
drawer.lineSegment(drawer.bounds.center, drawer.bounds.center + Vector2(state.difference, 0.0))
drawer.translate(0.0, 4.0)
drawer.stroke = ColorRGBa.BLUE
drawer.lineSegment(drawer.bounds.center, drawer.bounds.center + Vector2(state.differenceMax, 0.0))
}
}
}
}

View File

@@ -12,69 +12,67 @@ import org.openrndr.math.map
* [grid] is used to layout graphs on rows and columns.
*
*/
fun main() {
application {
configure {
width = 1280
height = 1080
}
program {
val font = loadFont("demo-data/fonts/IBMPlexMono-Regular.ttf", 20.0)
fun main() = application {
configure {
width = 1280
height = 1080
}
program {
val font = loadFont("demo-data/fonts/IBMPlexMono-Regular.ttf", 20.0)
// grid `columns * rows` must be >= Easing.values().size
val grid = drawer.bounds.grid(
3, 11, 10.0, 10.0, 10.0, 10.0
).flatten()
// grid `columns * rows` must be >= Easing.values().size
val grid = drawer.bounds.grid(
3, 11, 10.0, 10.0, 10.0, 10.0
).flatten()
// make pairs of (easing function, grid rectangle)
val pairs = Easing.values() zip grid
// make pairs of (easing function, grid rectangle)
val pairs = Easing.entries.toTypedArray() zip grid
extend {
// ~4 seconds animation loop
val animT = (frameCount % 240) / 60.0
extend {
// ~4 seconds animation loop
val animT = (frameCount % 240) / 60.0
pairs.forEach { (easing, gridRect) ->
pairs.forEach { (easing, gridRect) ->
// background rectangle
drawer.stroke = null
drawer.fill = ColorRGBa.WHITE.opacify(0.3)
drawer.rectangle(gridRect)
// background rectangle
drawer.stroke = null
drawer.fill = ColorRGBa.WHITE.opacify(0.3)
drawer.rectangle(gridRect)
// graph
drawer.stroke = ColorRGBa.PINK
val points = List(40) {
val curveT = it / 39.0
gridRect.position(
curveT, easing.function(curveT, 1.0, -1.0, 1.0)
)
}
drawer.lineStrip(points)
// label
drawer.fill = ColorRGBa.WHITE
drawer.stroke = null
drawer.fontMap = font
drawer.text(
easing.name,
// text position rounded for crisp font rendering
gridRect.position(0.02, 0.25).toInt().vector2
// graph
drawer.stroke = ColorRGBa.PINK
val points = List(40) {
val curveT = it / 39.0
gridRect.position(
curveT, easing.function(curveT, 1.0, -1.0, 1.0)
)
// animation
drawer.fill = ColorRGBa.WHITE.opacify(
when { // 4-stage opacity
animT > 3.0 -> 0.0 // invisible
animT > 2.0 -> 3.0 - animT // fade-out
animT < 1.0 -> animT // fade-in
else -> 1.0 // visible
}
)
// move only while visible (when loop time in 1.0..2.0)
val t = animT.map(1.0, 2.0, 0.0, 1.0, true)
val xy = Vector2(1.0, easing.function(t, 1.0, -1.0, 1.0))
drawer.circle(gridRect.position(xy), 5.0)
}
drawer.lineStrip(points)
// label
drawer.fill = ColorRGBa.WHITE
drawer.stroke = null
drawer.fontMap = font
drawer.text(
easing.name,
// text position rounded for crisp font rendering
gridRect.position(0.02, 0.25).toInt().vector2
)
// animation
drawer.fill = ColorRGBa.WHITE.opacify(
when { // 4-stage opacity
animT > 3.0 -> 0.0 // invisible
animT > 2.0 -> 3.0 - animT // fade-out
animT < 1.0 -> animT // fade-in
else -> 1.0 // visible
}
)
// move only while visible (when loop time in 1.0..2.0)
val t = animT.map(1.0, 2.0, 0.0, 1.0, true)
val xy = Vector2(1.0, easing.function(t, 1.0, -1.0, 1.0))
drawer.circle(gridRect.position(xy), 5.0)
}
}
}
}
}

View File

@@ -2,34 +2,32 @@ import org.openrndr.application
import org.openrndr.draw.loadFont
import org.openrndr.extra.envelopes.ADSRTracker
fun main() {
application {
program {
val tracker = ADSRTracker(this)
tracker.attack = 1.0
tracker.decay = 0.2
tracker.sustain = 0.8
tracker.release = 2.0
fun main() = application {
program {
val tracker = ADSRTracker(this)
tracker.attack = 1.0
tracker.decay = 0.2
tracker.sustain = 0.8
tracker.release = 2.0
keyboard.keyDown.listen {
if (it.name == "t")
tracker.triggerOn()
keyboard.keyDown.listen {
if (it.name == "t")
tracker.triggerOn()
}
keyboard.keyUp.listen {
if (it.name == "t")
tracker.triggerOff()
}
extend {
tracker.values().forEach {
drawer.circle(40.0, 40.0, 20.0 * it.value)
drawer.translate(40.0, 0.0)
}
keyboard.keyUp.listen {
if (it.name == "t")
tracker.triggerOff()
}
extend {
tracker.values().forEach {
drawer.circle(40.0, 40.0, 20.0 * it.value)
drawer.translate(40.0, 0.0)
}
drawer.defaults()
drawer.circle(drawer.bounds.center, 100.0 * tracker.value())
drawer.defaults()
drawer.circle(drawer.bounds.center, 100.0 * tracker.value())
drawer.fontMap = loadFont("demo-data/fonts/IBMPlexMono-Regular.ttf", 16.0)
drawer.text("press and hold 't'", 20.0, height - 20.0)
}
drawer.fontMap = loadFont("demo-data/fonts/IBMPlexMono-Regular.ttf", 16.0)
drawer.text("press and hold 't'", 20.0, height - 20.0)
}
}
}
}

View File

@@ -4,43 +4,41 @@ import org.openrndr.extra.envelopes.ADSRTracker
import org.openrndr.extra.noise.shapes.uniform
import org.openrndr.shape.Rectangle
fun main() {
application {
program {
val tracker = ADSRTracker(this)
tracker.attack = 1.0
tracker.decay = 0.2
tracker.sustain = 0.8
tracker.release = 2.0
fun main() = application {
program {
val tracker = ADSRTracker(this)
tracker.attack = 1.0
tracker.decay = 0.2
tracker.sustain = 0.8
tracker.release = 2.0
keyboard.keyDown.listen {
if (it.name == "t") {
val center = drawer.bounds.offsetEdges(-30.0).uniform()
tracker.triggerOn(0) { time, value, position ->
drawer.circle(center, value * 100.0)
}
}
if (it.name == "r") {
val center = drawer.bounds.offsetEdges(-30.0).uniform()
tracker.triggerOn(1) { time, value, position ->
val r = Rectangle.fromCenter(center, width = value * 100.0, height = value * 100.0)
drawer.rectangle(r)
}
keyboard.keyDown.listen {
if (it.name == "t") {
val center = drawer.bounds.offsetEdges(-30.0).uniform()
tracker.triggerOn(0) { time, value, position ->
drawer.circle(center, value * 100.0)
}
}
keyboard.keyUp.listen {
if (it.name == "t")
tracker.triggerOff(0)
if (it.name == "r")
tracker.triggerOff(1)
}
extend {
tracker.values().forEach {
it()
if (it.name == "r") {
val center = drawer.bounds.offsetEdges(-30.0).uniform()
tracker.triggerOn(1) { time, value, position ->
val r = Rectangle.fromCenter(center, width = value * 100.0, height = value * 100.0)
drawer.rectangle(r)
}
drawer.fontMap = loadFont("demo-data/fonts/IBMPlexMono-Regular.ttf", 16.0)
drawer.text("press and hold 't' and/or 'r'", 20.0, height - 20.0)
}
}
keyboard.keyUp.listen {
if (it.name == "t")
tracker.triggerOff(0)
if (it.name == "r")
tracker.triggerOff(1)
}
extend {
tracker.values().forEach {
it()
}
drawer.fontMap = loadFont("demo-data/fonts/IBMPlexMono-Regular.ttf", 16.0)
drawer.text("press and hold 't' and/or 'r'", 20.0, height - 20.0)
}
}
}
}

View File

@@ -4,43 +4,41 @@ import org.openrndr.extra.gui.GUI
import org.openrndr.extra.gui.addTo
import org.openrndr.extra.parameters.TextParameter
fun main() {
application {
program {
val gui = GUI()
gui.compartmentsCollapsedByDefault = false
fun main() = application {
program {
val gui = GUI()
gui.compartmentsCollapsedByDefault = false
val settings = object {
@TextParameter("x expression", order = 10)
var xExpression = "cos(t) * 50.0 + width / 2.0"
val settings = object {
@TextParameter("x expression", order = 10)
var xExpression = "cos(t) * 50.0 + width / 2.0"
@TextParameter("y expression", order = 20)
var yExpression = "sin(t) * 50.0 + height / 2.0"
@TextParameter("y expression", order = 20)
var yExpression = "sin(t) * 50.0 + height / 2.0"
@TextParameter("radius expression", order = 30)
var radiusExpression = "cos(t) * 50.0 + 50.0"
}.addTo(gui)
@TextParameter("radius expression", order = 30)
var radiusExpression = "cos(t) * 50.0 + 50.0"
}.addTo(gui)
extend(gui)
extend {
//gui.visible = mouse.position.x < 200.0
extend(gui)
extend {
//gui.visible = mouse.position.x < 200.0
val expressionContext =
mapOf("t" to seconds, "width" to drawer.bounds.width, "height" to drawer.bounds.height)
val expressionContext =
mapOf("t" to seconds, "width" to drawer.bounds.width, "height" to drawer.bounds.height)
fun eval(expression: String): Double =
try {
evaluateExpression(expression, expressionContext) ?: 0.0
} catch (e: Throwable) {
0.0
}
fun eval(expression: String): Double =
try {
evaluateExpression(expression, expressionContext) ?: 0.0
} catch (e: Throwable) {
0.0
}
val x = eval(settings.xExpression)
val y = eval(settings.yExpression)
val radius = eval(settings.radiusExpression)
val x = eval(settings.xExpression)
val y = eval(settings.yExpression)
val radius = eval(settings.radiusExpression)
drawer.circle(x, y, radius)
}
drawer.circle(x, y, radius)
}
}
}
}

View File

@@ -8,37 +8,35 @@ import org.openrndr.extra.parameters.TextParameter
* Improved version of DemoExpressionEvaluator01, it uses [watchingExpression1] to automatically convert an expression
* string into a function with a parameter "t".
*/
fun main() {
application {
program {
val gui = GUI()
gui.compartmentsCollapsedByDefault = false
fun main() = application {
program {
val gui = GUI()
gui.compartmentsCollapsedByDefault = false
// the constants used in our expressions
val constants = mutableMapOf("width" to drawer.width.toDouble(), "height" to drawer.height.toDouble())
// the constants used in our expressions
val constants = mutableMapOf("width" to drawer.width.toDouble(), "height" to drawer.height.toDouble())
val settings = object {
@TextParameter("x expression", order = 10)
var xExpression = "cos(t) * 50.0 + width / 2.0"
val settings = object {
@TextParameter("x expression", order = 10)
var xExpression = "cos(t) * 50.0 + width / 2.0"
@TextParameter("y expression", order = 20)
var yExpression = "sin(t) * 50.0 + height / 2.0"
@TextParameter("y expression", order = 20)
var yExpression = "sin(t) * 50.0 + height / 2.0"
@TextParameter("radius expression", order = 30)
var radiusExpression = "cos(t) * 50.0 + 50.0"
}.addTo(gui)
@TextParameter("radius expression", order = 30)
var radiusExpression = "cos(t) * 50.0 + 50.0"
}.addTo(gui)
val xFunction by watchingExpression1(settings::xExpression, "t", constants)
val yFunction by watchingExpression1(settings::yExpression, "t", constants)
val radiusFunction by watchingExpression1(settings::radiusExpression, "t", constants)
val xFunction by watchingExpression1(settings::xExpression, "t", constants)
val yFunction by watchingExpression1(settings::yExpression, "t", constants)
val radiusFunction by watchingExpression1(settings::radiusExpression, "t", constants)
extend(gui)
extend {
val x = xFunction(seconds)
val y = yFunction(seconds)
val radius = radiusFunction(seconds)
drawer.circle(x, y, radius)
}
extend(gui)
extend {
val x = xFunction(seconds)
val y = yFunction(seconds)
val radius = radiusFunction(seconds)
drawer.circle(x, y, radius)
}
}
}
}

View File

@@ -118,26 +118,25 @@ Drawing FCurves is useful for debugging, but their typical use is for animation.
The FCurve sampler allows us to query values for the given time value like this:
```kotlin
fun main() {
application {
program {
val xCurve = fcurve(
"""
M320 H0.4
S2,0, 2,320
S2,0, 2,320
S2,0, 2,320
S2,0, 2,320
T0.6,320
""".trimIndent()
).sampler() // <--
extend {
drawer.circle(
xCurve(seconds % 9.0),
height * 0.5,
20.0
)
}
fun main() = application {
program {
val xCurve = fcurve(
"""
M320 H0.4
S2,0, 2,320
S2,0, 2,320
S2,0, 2,320
S2,0, 2,320
T0.6,320
"""
)
val xCurveSampler = xCurve.sampler()
extend {
drawer.circle(
xCurveSampler(seconds % 9.0),
240.0,
20.0
)
}
}
}
@@ -194,6 +193,7 @@ For example `(M0 (h1 m1)[3])[2]` expands to `M0 h1 m1 h1 m1 h1 m1 M0 h1 m1 h1 m1
# References
* https://x.com/ruby0x1/status/1258252352672247814
* https://blender.stackexchange.com/questions/52403/what-is-the-mathematical-basis-for-f-curves/52468#52468
* https://pomax.github.io/bezierinfo/#yforx
@@ -210,6 +210,11 @@ For example `(M0 (h1 m1)[3])[2]` expands to `M0 h1 m1 h1 m1 h1 m1 M0 h1 m1 h1 m1
![DemoFCurve02Kt](https://raw.githubusercontent.com/openrndr/orx/media/orx-fcurve/images/DemoFCurve02Kt.png)
### DemoFCurve03
[source code](src/jvmDemo/kotlin/DemoFCurve03.kt)
![DemoFCurve03Kt](https://raw.githubusercontent.com/openrndr/orx/media/orx-fcurve/images/DemoFCurve03Kt.png)
### DemoFCurveSheet01
[source code](src/jvmDemo/kotlin/DemoFCurveSheet01.kt)

View File

@@ -1,19 +1,17 @@
import org.openrndr.application
import org.openrndr.extra.fcurve.fcurve
fun main() {
application {
configure {
width = 720
height = 720
}
program {
val xpos = fcurve("M0 Q4,360,5,720").sampler()
val ypos = fcurve("M360 h5").sampler()
fun main() = application {
configure {
width = 720
height = 720
}
program {
val xpos = fcurve("M0 Q4,360,5,720").sampler()
val ypos = fcurve("M360 h5").sampler()
extend {
drawer.circle(xpos(seconds.mod(5.0)), ypos(seconds.mod(5.0)), 100.0)
}
extend {
drawer.circle(xpos(seconds.mod(5.0)), ypos(seconds.mod(5.0)), 100.0)
}
}
}
}

View File

@@ -3,26 +3,24 @@ import org.openrndr.color.ColorRGBa
import org.openrndr.extra.fcurve.fcurve
import org.openrndr.math.Vector2
fun main() {
application {
configure {
width = 720
height = 720
}
program {
val xposCurve = fcurve("M0 Q4,360,5,720")
val xpos = xposCurve.sampler()
val yposCurve = fcurve("M360 h5")
val ypos = yposCurve.sampler()
fun main() = application {
configure {
width = 720
height = 720
}
program {
val xposCurve = fcurve("M0 Q4,360,5,720")
val xpos = xposCurve.sampler()
val yposCurve = fcurve("M360 h5")
val ypos = yposCurve.sampler()
extend {
drawer.circle(xpos(seconds.mod(5.0)), ypos(seconds.mod(5.0)), 100.0)
drawer.stroke = ColorRGBa.PINK
drawer.contours(xposCurve.contours(Vector2(720.0 / 5.0, -1.0), Vector2(0.0, height * 1.0)))
drawer.contours(yposCurve.contours(Vector2(720.0 / 5.0, -1.0), Vector2(0.0, height * 1.0)))
drawer.translate(seconds.mod(5.0)*(720.0/5.0), 0.0)
drawer.lineSegment(0.0, 0.0, 0.0, 720.0)
}
extend {
drawer.circle(xpos(seconds.mod(5.0)), ypos(seconds.mod(5.0)), 100.0)
drawer.stroke = ColorRGBa.PINK
drawer.contours(xposCurve.contours(Vector2(720.0 / 5.0, -1.0), Vector2(0.0, height * 1.0)))
drawer.contours(yposCurve.contours(Vector2(720.0 / 5.0, -1.0), Vector2(0.0, height * 1.0)))
drawer.translate(seconds.mod(5.0) * (720.0 / 5.0), 0.0)
drawer.lineSegment(0.0, 0.0, 0.0, 720.0)
}
}
}
}

View File

@@ -3,26 +3,26 @@ import org.openrndr.extra.fcurve.MultiFCurve
import org.openrndr.extra.fcurve.fcurve
import org.openrndr.extra.fcurve.vector2
fun main() {
application {
configure {
width = 720
height = 720
}
program {
class XYAnimation : MultiFCurve(mapOf(
fun main() = application {
configure {
width = 720
height = 720
}
program {
class XYAnimation : MultiFCurve(
mapOf(
"x" to fcurve("M0 Q4,360,5,720"),
"y" to fcurve("M360 h5")
)) {
val position = vector2("x", "y")
}
)
) {
val position = vector2("x", "y")
}
val xyAnimation = XYAnimation()
val position = xyAnimation.position.sampler()
val xyAnimation = XYAnimation()
val position = xyAnimation.position.sampler()
extend {
drawer.circle(position(seconds.mod(5.0)), 100.0)
}
extend {
drawer.circle(position(seconds.mod(5.0)), 100.0)
}
}
}
}

View File

@@ -9,148 +9,148 @@ import org.openrndr.math.Vector2
import org.openrndr.math.smoothstep
import org.openrndr.math.transforms.buildTransform
import org.openrndr.shape.LineSegment
import kotlin.math.*
import kotlin.math.max
import kotlin.random.Random
/**
* Demonstration of using FFT to filter a two-dimensional shape. Mouse xy-position is mapped
* to lowpass and highpass settings of the filter.
*/
fun main() {
application {
configure {
width = 720
height = 720
fun main() = application {
configure {
width = 720
height = 720
}
program {
val fftSize = 512
val fft = FFT(fftSize)
fun List<Vector2>.toFloatArrays(x: FloatArray, y: FloatArray) {
for ((index, segment) in this.withIndex()) {
x[index] = segment.x.toFloat()
y[index] = segment.y.toFloat()
}
}
program {
val fftSize = 512
val fft = FFT(fftSize)
fun List<Vector2>.toFloatArrays(x: FloatArray, y: FloatArray) {
for ((index, segment) in this.withIndex()) {
x[index] = segment.x.toFloat()
y[index] = segment.y.toFloat()
}
fun vectorsFromFloatArrays(x: FloatArray, y: FloatArray): List<Vector2> {
val n = x.size
val result = mutableListOf<Vector2>()
for (i in 0 until n) {
result.add(Vector2(x[i].toDouble(), y[i].toDouble()))
}
return result
}
fun lp(t: Double, c: Double): Double {
return smoothstep(c, c - 0.1, t)
}
fun hp(t: Double, c: Double): Double {
return smoothstep(c, c + 0.1, t)
}
val c = hobbyCurve(
drawer.bounds.scatter(30.0, distanceToEdge = 100.0, random = Random(3)).filter {
Random.nextBoolean()
},
true
).transform(buildTransform { translate(-drawer.bounds.center) })
val x = FloatArray(fftSize)
val y = FloatArray(fftSize)
val xFiltered = FloatArray(fftSize)
val yFiltered = FloatArray(fftSize)
extend {
c.equidistantPositions(fftSize).toFloatArrays(x, y)
// process x-component
fft.forward(x)
drawer.stroke = ColorRGBa.GRAY.shade(0.5)
drawer.lineSegments((0 until fft.size / 2).map {
LineSegment(
it.toDouble() * 2.0 + 0.5,
height * 0.5,
it.toDouble() * 2.0 + 0.5,
height * 0.5 - fft.magnitude(it) / 200.0,
)
})
val xpower = fft.magnitudeSum()
val hpc = mouse.position.x / width
val lpc = mouse.position.y / height
for (i in 1..fftSize / 2) {
val t = i.toDouble() / (fftSize / 2 - 1)
val f = if (hpc <= lpc) lp(t, lpc) * hp(t, hpc) else max(lp(t, lpc), hp(t, hpc))
fft.scaleBand(i, f.toFloat())
}
val xfpower = fft.magnitudeSum().coerceAtLeast(1.0)
fft.scaleAll((xpower / xfpower).toFloat())
drawer.stroke = ColorRGBa.PINK.opacify(0.8)
drawer.lineSegments((0 until fft.size / 2).map {
LineSegment(
it.toDouble() * 2.0 + 0.5,
height * 0.5,
it.toDouble() * 2.0 + 0.5,
height * 0.5 - fft.magnitude(it) / 200.0
)
})
fft.inverse(xFiltered)
// process y-component
fft.forward(y)
val ypower = fft.magnitudeSum()
drawer.stroke = ColorRGBa.GRAY.shade(0.5)
drawer.lineSegments((0 until fft.size / 2).map {
LineSegment(
it * 2.0 + 0.5,
height * 0.5,
it * 2.0 + 0.5,
height * 0.5 + fft.magnitude(it) / 200.0,
)
})
for (i in 1..fftSize / 2) {
val t = i.toDouble() / (fftSize / 2 - 1)
val f = if (hpc <= lpc) lp(t, lpc) * hp(t, hpc) else max(lp(t, lpc), hp(t, hpc))
fft.scaleBand(i, f.toFloat())
}
fun vectorsFromFloatArrays(x: FloatArray, y: FloatArray): List<Vector2> {
val n = x.size
val result = mutableListOf<Vector2>()
for (i in 0 until n) {
result.add(Vector2(x[i].toDouble(), y[i].toDouble()))
}
return result
}
val yfpower = fft.magnitudeSum().coerceAtLeast(1.0)
fun lp(t: Double, c: Double): Double {
return smoothstep(c, c - 0.1, t)
}
fft.scaleAll((ypower / yfpower).toFloat())
drawer.stroke = ColorRGBa.PINK.opacify(0.7)
drawer.lineSegments((0 until fft.size / 2).map {
LineSegment(
it * 2.0 + 0.5,
height * 0.5,
it * 2.0 + 0.5,
height * 0.5 + fft.magnitude(it) / 200.0,
)
})
fft.inverse(yFiltered)
fun hp(t: Double, c: Double): Double {
return smoothstep(c, c + 0.1, t)
}
val cr = vectorsFromFloatArrays(xFiltered, yFiltered).catmullRom(closed = true).toContour()
//val cr = ShapeContour.fromPoints(vectorsFromFloatArrays(xr, yr), closed=true)
val c = hobbyCurve(
drawer.bounds.scatter(40.0, distanceToEdge = 100.0, random = Random(0)),
true
).transform(buildTransform { translate(-drawer.bounds.center) })
val recenteredShape = cr.transform(buildTransform {
translate(drawer.bounds.center)
})
drawer.fill = null
drawer.stroke = ColorRGBa.WHITE
val x = FloatArray(fftSize)
val y = FloatArray(fftSize)
drawer.lineSegment(mouse.position.x / width * 512, 0.0, mouse.position.x / width * 512, height * 1.0)
drawer.lineSegment(mouse.position.y / height * 512, 0.0, mouse.position.y / height * 512, height * 1.0)
val xFiltered = FloatArray(fftSize)
val yFiltered = FloatArray(fftSize)
extend {
c.equidistantPositions(fftSize).toFloatArrays(x, y)
// process x-component
fft.forward(x)
drawer.stroke = ColorRGBa.GRAY.shade(0.5)
drawer.lineSegments((0 until fft.size / 2).map {
LineSegment(
it.toDouble() * 2.0 + 0.5,
height * 0.5,
it.toDouble() * 2.0 + 0.5,
height * 0.5 - fft.magnitude(it) / 200.0,
)
})
val xpower = fft.magnitudeSum()
val lpc = mouse.position.x / width
val hpc = mouse.position.y / height
for (i in 1..fftSize / 2) {
val t = i.toDouble() / (fftSize / 2 - 1)
val f = if (hpc <= lpc) lp(t, lpc) * hp(t, hpc) else max(lp(t, lpc), hp(t, hpc))
fft.scaleBand(i, f.toFloat())
}
val xfpower = fft.magnitudeSum().coerceAtLeast(1.0)
fft.scaleAll((xpower / xfpower).toFloat())
drawer.stroke = ColorRGBa.PINK.opacify(0.8)
drawer.lineSegments((0 until fft.size / 2).map {
LineSegment(
it.toDouble() * 2.0 + 0.5,
height * 0.5,
it.toDouble() * 2.0 + 0.5,
height * 0.5 - fft.magnitude(it) / 200.0
)
})
fft.inverse(xFiltered)
// process y-component
fft.forward(y)
val ypower = fft.magnitudeSum()
drawer.stroke = ColorRGBa.GRAY.shade(0.5)
drawer.lineSegments((0 until fft.size / 2).map {
LineSegment(
it.toDouble() * 2.0 + 0.5,
height * 0.5,
it.toDouble() * 2.0 + 0.5,
height * 0.5 + fft.magnitude(it) / 200.0,
)
})
for (i in 1..fftSize / 2) {
val t = i.toDouble() / (fftSize / 2 - 1)
val f = if (hpc <= lpc) lp(t, lpc) * hp(t, hpc) else max(lp(t, lpc), hp(t, hpc))
fft.scaleBand(i, f.toFloat())
}
val yfpower = fft.magnitudeSum().coerceAtLeast(1.0)
fft.scaleAll((ypower / yfpower).toFloat())
drawer.stroke = ColorRGBa.PINK.opacify(0.7)
drawer.lineSegments((0 until fft.size / 2).map {
LineSegment(
it.toDouble() * 2.0 + 0.5,
height * 0.5,
it.toDouble() * 2.0 + 0.5,
height * 0.5 + fft.magnitude(it) / 200.0,
)
})
fft.inverse(yFiltered)
val cr = vectorsFromFloatArrays(xFiltered, yFiltered).catmullRom(closed = true).toContour()
//val cr = ShapeContour.fromPoints(vectorsFromFloatArrays(xr, yr), closed=true)
val recenteredShape = cr.transform(buildTransform {
translate(drawer.bounds.center)
})
drawer.fill = null
drawer.stroke = ColorRGBa.WHITE
drawer.lineSegment(mouse.position.x / width * 512, 0.0, mouse.position.x / width * 512, height * 1.0)
drawer.lineSegment(mouse.position.y / height * 512, 0.0, mouse.position.y / height * 512, height * 1.0)
drawer.contour(recenteredShape)
}
drawer.contour(recenteredShape)
}
}
}
}

View File

@@ -1,29 +1,28 @@
import org.openrndr.application
import org.openrndr.extra.fx.blend.*
fun main() {
application {
program {
val add = Add()
val colorBurn = ColorBurn()
val colorDodge = ColorDodge()
val darken = Darken()
val destIn = DestinationIn()
val destOut = DestinationOut()
val destAtop = DestinationAtop()
val hardLight = HardLight()
val lighten = Lighten()
val multiply = Multiply()
val multiplyContrast = MultiplyContrast()
val normal = Normal()
val overlay = Overlay()
val passthrough = Passthrough()
val screen = Screen()
val sourceIn = SourceIn()
val sourceAtop = SourceAtop()
val sourceOut = SourceOut()
val subtract = Subtract()
val xor = Xor()
application.exit()
}
fun main() = application {
program {
val add = Add()
val colorBurn = ColorBurn()
val colorDodge = ColorDodge()
val darken = Darken()
val destIn = DestinationIn()
val destOut = DestinationOut()
val destAtop = DestinationAtop()
val hardLight = HardLight()
val lighten = Lighten()
val multiply = Multiply()
val multiplyContrast = MultiplyContrast()
val normal = Normal()
val overlay = Overlay()
val passthrough = Passthrough()
val screen = Screen()
val sourceIn = SourceIn()
val sourceAtop = SourceAtop()
val sourceOut = SourceOut()
val subtract = Subtract()
val xor = Xor()
application.exit()
}
}
}

View File

@@ -5,106 +5,117 @@ import org.openrndr.extra.fx.blur.*
import org.openrndr.math.Polar
import kotlin.math.sin
fun main() {
application {
program {
// In this buffer we will draw some simple shapes
val dry = renderTarget(width / 3, height / 3) {
colorBuffer()
fun main() = application {
program {
// In this buffer we will draw some simple shapes
val dry = renderTarget(width / 3, height / 3) {
colorBuffer()
}
// The list of effects to demo
val effects = listOf(
BoxBlur(),
ApproximateGaussianBlur(),
HashBlur(),
GaussianBlur(),
GaussianBloom(),
FrameBlur(),
ZoomBlur(),
LaserBlur()
)
// On this buffer we will draw the dry buffer with an effect applied
val wet = colorBuffer(dry.width, dry.height)
val font = loadFont("demo-data/fonts/IBMPlexMono-Regular.ttf", 16.0)
extend {
// Draw two moving circles
drawer.isolatedWithTarget(dry) {
clear(ColorRGBa.BLACK)
fill = null
stroke = ColorRGBa.PINK
strokeWeight = 25.0
circle(
bounds.center +
Polar(seconds * 50.0, 100.0).cartesian,
200.0 + 50.0 * sin(seconds * 2.0)
)
fill = ColorRGBa.PINK
stroke = null
circle(
bounds.center +
Polar(seconds * 50.0 + 60, 100.0).cartesian,
100.0 + 20.0 * sin(seconds * 2.0 + 1)
)
}
// The list of effects to demo
val effects = listOf(
BoxBlur(),
ApproximateGaussianBlur(),
HashBlur(),
GaussianBlur(),
GaussianBloom(),
FrameBlur(),
ZoomBlur(),
LaserBlur()
)
effects.forEachIndexed { i, blur ->
// Adjust the effect settings.
// All the values could be animated.
when (blur) {
is BoxBlur -> {
blur.window = 30
}
// On this buffer we will draw the dry buffer with an effect applied
val wet = colorBuffer(dry.width, dry.height)
is ApproximateGaussianBlur -> {
blur.window = 25
blur.sigma = 15.0
}
val font = loadFont("demo-data/fonts/IBMPlexMono-Regular.ttf", 16.0)
is HashBlur -> {
blur.samples = 50
blur.radius = 5.0
blur.time = seconds
}
extend {
// Draw two moving circles
drawer.isolatedWithTarget(dry) {
clear(ColorRGBa.BLACK)
is GaussianBlur -> {
blur.window = 25
blur.sigma = 15.0
}
fill = null
stroke = ColorRGBa.PINK
strokeWeight = 25.0
circle(bounds.center +
Polar(seconds * 50.0, 100.0).cartesian,
200.0 + 50.0 * sin(seconds * 2.0))
is GaussianBloom -> {
blur.window = 5
blur.sigma = 3.0
blur.gain = 3.0
blur.noiseSeed = seconds
}
fill = ColorRGBa.PINK
stroke = null
circle(bounds.center +
Polar(seconds * 50.0 + 60, 100.0).cartesian,
100.0 + 20.0 * sin(seconds * 2.0 + 1))
is FrameBlur -> {
blur.blend = 0.05
}
is ZoomBlur -> {
blur.center = Polar(seconds * 77.0, 0.5)
.cartesian
blur.strength = 0.8
}
is LaserBlur -> {
blur.center = Polar(seconds * 77.0, 0.5)
.cartesian
blur.aberration = 0.03
blur.radius = 0.5
}
}
effects.forEachIndexed { i, blur ->
// Adjust the effect settings.
// All the values could be animated.
when (blur) {
is BoxBlur -> {
blur.window = 30
}
is ApproximateGaussianBlur -> {
blur.window = 25
blur.sigma = 15.0
}
is HashBlur -> {
blur.samples = 50
blur.radius = 5.0
blur.time = seconds
}
is GaussianBlur -> {
blur.window = 25
blur.sigma = 15.0
}
is GaussianBloom -> {
blur.window = 5
blur.sigma = 3.0
blur.gain = 3.0
blur.noiseSeed = seconds
}
is FrameBlur -> {
blur.blend = 0.05
}
is ZoomBlur -> {
blur.center = Polar(seconds * 77.0, 0.5)
.cartesian
blur.strength = 0.8
}
is LaserBlur -> {
blur.center = Polar(seconds * 77.0, 0.5)
.cartesian
blur.aberration = 0.03
blur.radius = 0.5
// Apply the effect on `dry` writing the result to `wet`
blur.apply(dry.colorBuffer(0), wet)
}
}
// Apply the effect on `dry` writing the result to `wet`
blur.apply(dry.colorBuffer(0), wet)
// Draw `wet` and write the effect name on top
drawer.isolated {
translate((i % 3) * width / 3.0,
(i / 3) * height / 3.0)
image(wet)
fontMap = font
text(blur.javaClass.simpleName, 20.0, 30.0)
}
// Draw `wet` and write the effect name on top
drawer.isolated {
translate(
(i % 3) * width / 3.0,
(i / 3) * height / 3.0
)
image(wet)
fontMap = font
text(blur.javaClass.simpleName, 20.0, 30.0)
}
}
}
}
}
}

View File

@@ -3,19 +3,17 @@ import org.openrndr.draw.createEquivalent
import org.openrndr.draw.loadImage
import org.openrndr.extra.fx.color.Duotone
fun main() {
application {
program {
fun main() = application {
program {
val image = loadImage("demo-data/images/image-001.png")
val filteredImage = image.createEquivalent()
val duotone = Duotone()
val image = loadImage("demo-data/images/image-001.png")
val filteredImage = image.createEquivalent()
val duotone = Duotone()
extend {
duotone.labInterpolation = seconds.mod(2.0) < 1.0
duotone.apply(image, filteredImage)
drawer.image(filteredImage)
}
extend {
duotone.labInterpolation = seconds.mod(2.0) < 1.0
duotone.apply(image, filteredImage)
drawer.image(filteredImage)
}
}
}
}

View File

@@ -3,18 +3,16 @@ import org.openrndr.draw.createEquivalent
import org.openrndr.draw.loadImage
import org.openrndr.extra.fx.color.Posterize
fun main() {
application {
program {
val image = loadImage("demo-data/images/image-001.png")
val filteredImage = image.createEquivalent()
val posterize = Posterize()
fun main() = application {
program {
val image = loadImage("demo-data/images/image-001.png")
val filteredImage = image.createEquivalent()
val posterize = Posterize()
extend {
posterize.levels = 2
posterize.apply(image, filteredImage)
drawer.image(filteredImage)
}
extend {
posterize.levels = 2
posterize.apply(image, filteredImage)
drawer.image(filteredImage)
}
}
}
}

View File

@@ -5,17 +5,15 @@ import org.openrndr.draw.loadImage
import org.openrndr.extra.fx.colormap.GrayscaleColormap
import kotlin.math.sin
fun main() {
application {
program {
val colormap = GrayscaleColormap()
val image = loadImage("demo-data/images/image-001.png")
val colormapImage = image.createEquivalent(type = ColorType.FLOAT32)
extend {
colormap.curve = 1.0 + sin(seconds) * .5
colormap.apply(image, colormapImage)
drawer.image(colormapImage)
}
fun main() = application {
program {
val colormap = GrayscaleColormap()
val image = loadImage("demo-data/images/image-001.png")
val colormapImage = image.createEquivalent(type = ColorType.FLOAT32)
extend {
colormap.curve = 1.0 + sin(seconds) * .5
colormap.apply(image, colormapImage)
drawer.image(colormapImage)
}
}
}
}

View File

@@ -5,17 +5,15 @@ import org.openrndr.draw.loadImage
import org.openrndr.extra.fx.colormap.SpectralZucconiColormap
import kotlin.math.sin
fun main() {
application {
program {
val colormap = SpectralZucconiColormap()
val image = loadImage("demo-data/images/image-001.png")
val colormapImage = image.createEquivalent(type = ColorType.FLOAT32)
extend {
colormap.curve = 1.0 + sin(seconds) * .5
colormap.apply(image, colormapImage)
drawer.image(colormapImage)
}
fun main() = application {
program {
val colormap = SpectralZucconiColormap()
val image = loadImage("demo-data/images/image-001.png")
val colormapImage = image.createEquivalent(type = ColorType.FLOAT32)
extend {
colormap.curve = 1.0 + sin(seconds) * .5
colormap.apply(image, colormapImage)
drawer.image(colormapImage)
}
}
}
}

View File

@@ -5,17 +5,15 @@ import org.openrndr.draw.loadImage
import org.openrndr.extra.fx.colormap.TurboColormap
import kotlin.math.sin
fun main() {
application {
program {
val colormap = TurboColormap()
val image = loadImage("demo-data/images/image-001.png")
val colormapImage = image.createEquivalent(type = ColorType.FLOAT32)
extend {
colormap.curve = 1.0 + sin(seconds) * .5
colormap.apply(image, colormapImage)
drawer.image(colormapImage)
}
fun main() = application {
program {
val colormap = TurboColormap()
val image = loadImage("demo-data/images/image-001.png")
val colormapImage = image.createEquivalent(type = ColorType.FLOAT32)
extend {
colormap.curve = 1.0 + sin(seconds) * .5
colormap.apply(image, colormapImage)
drawer.image(colormapImage)
}
}
}
}

View File

@@ -11,53 +11,55 @@ import org.openrndr.extra.noise.*
import org.openrndr.math.smoothstep
import kotlin.math.cos
fun main() {
application {
program {
extend(Post()) {
// -- create a color buffer and fill it with random direction vectors
val direction = colorBuffer(width, height, type = ColorType.FLOAT32)
val s = direction.shadow
val n = simplex2D.bipolar().fbm().scaleShiftInput(0.01, 0.0, 0.01, 0.0).withVector2Output()
val ng = simplex2D.unipolar().scaleShiftInput(0.005, 0.0, 0.005, 0.0)
for (y in 0 until height) {
for (x in 0 until width) {
val a = smoothstep(0.4, 0.6, cos((x + y) * 0.01) * 0.5 + 0.5)
val nv = n(2320, x.toDouble(), y.toDouble()) * smoothstep(0.45, 0.55, ng(1032, x.toDouble(), y.toDouble()))
s[x, y] = ColorRGBa(nv.x, nv.y, 0.0, 1.0)
}
fun main() = application {
program {
extend(Post()) {
// -- create a color buffer and fill it with random direction vectors
val direction = colorBuffer(width, height, type = ColorType.FLOAT32)
val s = direction.shadow
val n = simplex2D.bipolar().fbm().scaleShiftInput(0.01, 0.0, 0.01, 0.0).withVector2Output()
val ng = simplex2D.unipolar().scaleShiftInput(0.005, 0.0, 0.005, 0.0)
for (y in 0 until height) {
for (x in 0 until width) {
val a = smoothstep(0.4, 0.6, cos((x + y) * 0.01) * 0.5 + 0.5)
val nv = n(2320, x.toDouble(), y.toDouble()) * smoothstep(
0.45,
0.55,
ng(1032, x.toDouble(), y.toDouble())
)
s[x, y] = ColorRGBa(nv.x, nv.y, 0.0, 1.0)
}
s.upload()
}
s.upload()
val directional = DirectionalBlur()
val directional = DirectionalBlur()
// -- create a bidirectional composite filter by using a directional filter twice
val bidirectional = directional.then(directional) {
firstParameters {
window = 50
perpendicular = false
}
secondParameters {
window = 3
perpendicular = true
}
// -- create a bidirectional composite filter by using a directional filter twice
val bidirectional = directional.then(directional) {
firstParameters {
window = 50
perpendicular = false
}
val grain = FilmGrain()
grain.grainStrength = 1.0
// -- create a grain-blur composite filter
val grainBlur = grain.then(bidirectional)
post { input, output ->
grainBlur.apply(arrayOf(input, direction), output)
secondParameters {
window = 3
perpendicular = true
}
}
val image = loadImage("demo-data/images/image-001.png")
extend {
drawer.image(image)
val grain = FilmGrain()
grain.grainStrength = 1.0
// -- create a grain-blur composite filter
val grainBlur = grain.then(bidirectional)
post { input, output ->
grainBlur.apply(arrayOf(input, direction), output)
}
}
val image = loadImage("demo-data/images/image-001.png")
extend {
drawer.image(image)
}
}
}
}

View File

@@ -3,23 +3,21 @@ import org.openrndr.draw.createEquivalent
import org.openrndr.draw.loadImage
import org.openrndr.extra.fx.dither.LumaHalftone
fun main() {
application {
program {
val image = loadImage("demo-data/images/image-001.png")
val filteredImage = image.createEquivalent()
val lumaHalftone = LumaHalftone()
extend {
lumaHalftone.rotation = -15.0
lumaHalftone.freq0 = 100.0
lumaHalftone.gain1 = 1.0
lumaHalftone.threshold = 0.5
lumaHalftone.phase0 = seconds*0.1
lumaHalftone.phase1 = -seconds*0.1
lumaHalftone.apply(image, filteredImage)
lumaHalftone.invert = seconds.mod(2.0) < 1.0
drawer.image(filteredImage)
}
fun main() = application {
program {
val image = loadImage("demo-data/images/image-001.png")
val filteredImage = image.createEquivalent()
val lumaHalftone = LumaHalftone()
extend {
lumaHalftone.rotation = -15.0
lumaHalftone.freq0 = 100.0
lumaHalftone.gain1 = 1.0
lumaHalftone.threshold = 0.5
lumaHalftone.phase0 = seconds * 0.1
lumaHalftone.phase1 = -seconds * 0.1
lumaHalftone.apply(image, filteredImage)
lumaHalftone.invert = seconds.mod(2.0) < 1.0
drawer.image(filteredImage)
}
}
}
}

View File

@@ -5,28 +5,26 @@ import org.openrndr.extensions.SingleScreenshot
import org.openrndr.extra.fx.distort.FluidDistort
import org.openrndr.extra.fx.patterns.Checkers
fun main() {
application {
program {
val fd = FluidDistort()
val checkers = Checkers()
fun main() = application {
program {
val fd = FluidDistort()
val checkers = Checkers()
val image = colorBuffer(width, height)
val distorted = image.createEquivalent()
checkers.size = 64.0
checkers.apply(emptyArray(), image)
val image = colorBuffer(width, height)
val distorted = image.createEquivalent()
checkers.size = 64.0
checkers.apply(emptyArray(), image)
if (System.getProperty("takeScreenshot") == "true") {
extensions.filterIsInstance<SingleScreenshot>().forEach {
it.delayFrames = 150
}
}
extend {
// Ensure >0.01 for a better screenshot
fd.blend = (mouse.position.x / width).coerceAtLeast(0.01)
fd.apply(image, distorted)
drawer.image(distorted)
if (System.getProperty("takeScreenshot") == "true") {
extensions.filterIsInstance<SingleScreenshot>().forEach {
it.delayFrames = 150
}
}
extend {
// Ensure >0.01 for a better screenshot
fd.blend = (mouse.position.x / width).coerceAtLeast(0.01)
fd.apply(image, distorted)
drawer.image(distorted)
}
}
}
}

View File

@@ -1,27 +1,25 @@
import org.openrndr.extra.fx.color.RgbToOkLab
import org.openrndr.extra.fx.color.OkLabToRgb
import org.openrndr.application
import org.openrndr.draw.ColorType
import org.openrndr.draw.createEquivalent
import org.openrndr.draw.loadImage
import org.openrndr.extra.fx.color.OkLabToRgb
import org.openrndr.extra.fx.color.RgbToOkLab
/**
* This demonstrates converting a [ColorBuffer] from and to (OK)LAB color space using the [RgbToOkLab] and [OkLabToRgb]
* filters. The (OK)Lab representation is signed and requires a floating point representation.
*/
fun main() {
application {
program {
val rgbToOkLab = RgbToOkLab()
val okLabToRgb = OkLabToRgb()
val image = loadImage("demo-data/images/image-001.png")
val labImage = image.createEquivalent(type = ColorType.FLOAT32)
rgbToOkLab.apply(image, labImage)
okLabToRgb.apply(labImage, image)
extend {
drawer.image(image)
}
fun main() = application {
program {
val rgbToOkLab = RgbToOkLab()
val okLabToRgb = OkLabToRgb()
val image = loadImage("demo-data/images/image-001.png")
val labImage = image.createEquivalent(type = ColorType.FLOAT32)
rgbToOkLab.apply(image, labImage)
okLabToRgb.apply(labImage, image)
extend {
drawer.image(image)
}
}
}
}

View File

@@ -8,38 +8,36 @@ import org.openrndr.extra.fx.patterns.Checkers
import org.openrndr.math.Vector2
import kotlin.math.sin
fun main() {
application {
configure {
width = 800
height = 800
fun main() = application {
configure {
width = 800
height = 800
}
program {
val a = drawImage(width, height) {
drawer.stroke = null
drawer.fill = ColorRGBa.BLUE
drawer.circle(drawer.bounds.center - Vector2(100.0, 0.0), drawer.width * 0.25)
}
program {
val a = drawImage(width, height) {
drawer.stroke = null
drawer.fill = ColorRGBa.BLUE
drawer.circle(drawer.bounds.center - Vector2(100.0, 0.0), drawer.width * 0.25)
}
val b = drawImage(width, height) {
drawer.clear(ColorRGBa.TRANSPARENT)
drawer.stroke = ColorRGBa.RED
drawer.strokeWeight = 10.0
drawer.fill = ColorRGBa.YELLOW.opacify(1.0)
drawer.circle(drawer.bounds.center + Vector2(100.0, 0.0), drawer.width * 0.25)
}
BoxBlur().apply { window = 10 }.apply(b, b)
val checked = a.createEquivalent()
Checkers().apply(emptyArray(), checked)
val b = drawImage(width, height) {
drawer.clear(ColorRGBa.TRANSPARENT)
drawer.stroke = ColorRGBa.RED
drawer.strokeWeight = 10.0
drawer.fill = ColorRGBa.YELLOW.opacify(1.0)
drawer.circle(drawer.bounds.center + Vector2(100.0, 0.0), drawer.width * 0.25)
}
BoxBlur().apply { window = 10 }.apply(b, b)
val checked = a.createEquivalent()
Checkers().apply(emptyArray(), checked)
val mixed = a.createEquivalent()
val blendSpectral = BlendSpectral()
extend {
drawer.image(checked)
blendSpectral.fill = sin(seconds) * 0.5 + 0.5
blendSpectral.clip = seconds.mod(4.0) > 2.0
blendSpectral.apply(a, b, mixed)
drawer.image(mixed)
}
val mixed = a.createEquivalent()
val blendSpectral = BlendSpectral()
extend {
drawer.image(checked)
blendSpectral.fill = sin(seconds) * 0.5 + 0.5
blendSpectral.clip = seconds.mod(4.0) > 2.0
blendSpectral.apply(a, b, mixed)
drawer.image(mixed)
}
}
}
}

View File

@@ -10,21 +10,19 @@ import kotlin.random.Random
* - Filters the generated points to enforce a minimum distance of 20.0 units between them.
* - Visualizes the filtered points as circles with a radius of 10.0 units on the canvas.
*/
fun main() {
application {
configure {
width = 720
height = 720
fun main() = application {
configure {
width = 720
height = 720
}
program {
val r = Random(0)
val points = (0 until 10000).map {
drawer.bounds.uniform(random = r)
}
program {
val r = Random(0)
val points = (0 until 10000).map {
drawer.bounds.uniform(random = r)
}
val filteredPoints = points.filter(20.0)
extend {
drawer.circles(filteredPoints, 10.0)
}
val filteredPoints = points.filter(20.0)
extend {
drawer.circles(filteredPoints, 10.0)
}
}
}
}

View File

@@ -13,32 +13,29 @@ import kotlin.random.Random
* - Rectangles representing the bounds of the cells in the grid.
* - Circles representing the generated points.
*/
fun main() {
application {
configure {
width = 720
height = 720
}
program {
val r = Random(0)
val hashGrid = HashGrid(72.0)
fun main() = application {
configure {
width = 720
height = 720
}
program {
val r = Random(0)
val hashGrid = HashGrid(72.0)
extend {
for (i in 0 until 100) {
val p = drawer.bounds.uniform(random = r)
if (hashGrid.isFree(p)) {
hashGrid.insert(p)
}
extend {
for (i in 0 until 100) {
val p = drawer.bounds.uniform(random = r)
if (hashGrid.isFree(p)) {
hashGrid.insert(p)
}
drawer.fill = null
drawer.stroke = ColorRGBa.WHITE
drawer.rectangles(hashGrid.cells().map { it.bounds }.toList())
drawer.fill = null
drawer.stroke = ColorRGBa.PINK
drawer.circles(hashGrid.points().map { it.first }.toList(), 36.0)
}
drawer.fill = null
drawer.stroke = ColorRGBa.WHITE
drawer.rectangles(hashGrid.cells().map { it.bounds }.toList())
drawer.fill = null
drawer.stroke = ColorRGBa.PINK
drawer.circles(hashGrid.points().map { it.first }.toList(), 36.0)
}
}
}
}

View File

@@ -12,54 +12,56 @@ import org.openrndr.draw.loadImage
import kotlin.math.cos
import kotlin.math.sin
fun main() {
application {
program {
// Load an image, convert to BoofCV format using orx-boofcv
val input = loadImage("demo-data/images/image-001.png").toGrayF32()
fun main() = application {
program {
// Load an image, convert to BoofCV format using orx-boofcv
val input = loadImage("demo-data/images/image-001.png").toGrayF32()
// BoofCV: calculate a good threshold for the loaded image
val threshold = GThresholdImageOps.computeOtsu(input, 0.0, 255.0)
// BoofCV: calculate a good threshold for the loaded image
val threshold = GThresholdImageOps.computeOtsu(input, 0.0, 255.0)
// BoofCV: use the threshold to convert the image to black and white
val binary = GrayU8(input.width, input.height)
ThresholdImageOps.threshold(input, binary, threshold.toFloat(), false)
// BoofCV: use the threshold to convert the image to black and white
val binary = GrayU8(input.width, input.height)
ThresholdImageOps.threshold(input, binary, threshold.toFloat(), false)
// BoofCV: Contract and expand the white areas to remove noise
var filtered = BinaryImageOps.erode8(binary, 1, null)
filtered = BinaryImageOps.dilate8(filtered, 1, null)
// BoofCV: Contract and expand the white areas to remove noise
var filtered = BinaryImageOps.erode8(binary, 1, null)
filtered = BinaryImageOps.dilate8(filtered, 1, null)
// BoofCV: Calculate contours as vector data
val contours = BinaryImageOps.contour(filtered, ConnectRule.EIGHT, null)
// BoofCV: Calculate contours as vector data
val contours = BinaryImageOps.contour(filtered, ConnectRule.EIGHT, null)
// orx-boofcv: convert vector data to OPENRNDR ShapeContours
val externalShapes = contours.toShapeContours(true,
internal = false, external = true)
val internalShapes = contours.toShapeContours(true,
internal = true, external = false)
// orx-boofcv: convert vector data to OPENRNDR ShapeContours
val externalShapes = contours.toShapeContours(
true,
internal = false, external = true
)
val internalShapes = contours.toShapeContours(
true,
internal = true, external = false
)
extend {
drawer.run {
// Zoom in and out over time
translate(bounds.center)
scale(1.5 + 0.5 * cos(seconds * 0.2))
translate(-bounds.center)
extend {
drawer.run {
// Zoom in and out over time
translate(bounds.center)
scale(1.5 + 0.5 * cos(seconds * 0.2))
translate(-bounds.center)
stroke = null
stroke = null
// Draw all external shapes
fill = rgb(0.2)
contours(externalShapes)
// Draw all external shapes
fill = rgb(0.2)
contours(externalShapes)
// Draw internal shapes one by one to set unique colors
internalShapes.forEachIndexed { i, shp ->
val shade = 0.2 + (i % 7) * 0.1 +
0.1 * sin(i + seconds)
fill = ColorRGBa.PINK.shade(shade)
contour(shp)
}
// Draw internal shapes one by one to set unique colors
internalShapes.forEachIndexed { i, shp ->
val shade = 0.2 + (i % 7) * 0.1 +
0.1 * sin(i + seconds)
fill = ColorRGBa.PINK.shade(shade)
contour(shp)
}
}
}
}
}
}

View File

@@ -3,24 +3,21 @@ import org.openrndr.boofcv.binding.resizeBy
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.loadImage
fun main() = application {
program {
// Load an image, convert to BoofCV format using orx-boofcv
val input = loadImage("demo-data/images/image-001.png")
fun main() {
application {
program {
// Load an image, convert to BoofCV format using orx-boofcv
val input = loadImage("demo-data/images/image-001.png")
val scaled = input.resizeBy(0.5)
val scaled2 = input.resizeBy(0.25, convertToGray = true)
val scaled3 = input.resizeBy(0.1)
val scaled = input.resizeBy(0.5)
val scaled2 = input.resizeBy(0.25, convertToGray = true)
val scaled3 = input.resizeBy(0.1)
extend {
drawer.clear(ColorRGBa.BLACK)
drawer.translate(0.0, (height - scaled.bounds.height) / 2.0)
drawer.image(scaled)
drawer.image(scaled2, scaled.bounds.width, scaled.bounds.height - scaled2.height)
drawer.image(scaled3, scaled.bounds.width + scaled2.bounds.width, scaled.bounds.height - scaled3.height)
}
extend {
drawer.clear(ColorRGBa.BLACK)
drawer.translate(0.0, (height - scaled.bounds.height) / 2.0)
drawer.image(scaled)
drawer.image(scaled2, scaled.bounds.width, scaled.bounds.height - scaled2.height)
drawer.image(scaled3, scaled.bounds.width + scaled2.bounds.width, scaled.bounds.height - scaled3.height)
}
}
}
}

View File

@@ -3,23 +3,20 @@ import org.openrndr.boofcv.binding.resizeTo
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.loadImage
fun main() = application {
program {
// Load an image, convert to BoofCV format using orx-boofcv
val input = loadImage("demo-data/images/image-001.png")
val scaled = input.resizeTo(input.width / 3)
val scaled2 = input.resizeTo(newHeight = input.height / 4, convertToGray = true)
val scaled3 = input.resizeTo(input.width / 5, input.height / 5)
fun main() {
application {
program {
// Load an image, convert to BoofCV format using orx-boofcv
val input = loadImage("demo-data/images/image-001.png")
val scaled = input.resizeTo(input.width / 3)
val scaled2 = input.resizeTo(newHeight = input.height / 4, convertToGray = true)
val scaled3 = input.resizeTo(input.width / 5, input.height / 5)
extend {
drawer.clear(ColorRGBa.BLACK)
drawer.translate(0.0, (height - scaled.bounds.height) / 2.0)
drawer.image(scaled)
drawer.image(scaled2, scaled.bounds.width, scaled.bounds.height - scaled2.height)
drawer.image(scaled3, scaled.bounds.width + scaled2.bounds.width, scaled.bounds.height - scaled3.height)
}
extend {
drawer.clear(ColorRGBa.BLACK)
drawer.translate(0.0, (height - scaled.bounds.height) / 2.0)
drawer.image(scaled)
drawer.image(scaled2, scaled.bounds.width, scaled.bounds.height - scaled2.height)
drawer.image(scaled3, scaled.bounds.width + scaled2.bounds.width, scaled.bounds.height - scaled3.height)
}
}
}
}

View File

@@ -17,63 +17,65 @@ import org.openrndr.math.Vector2
import org.openrndr.shape.Rectangle
import org.openrndr.shape.ShapeContour
fun main() {
application {
program {
// Create a buffer where to draw something for boofcv
val rt = renderTarget(width, height) {
colorBuffer()
depthBuffer()
}
// Draw some shapes on that buffer
drawer.isolatedWithTarget(rt) {
clear(ColorRGBa.BLACK)
fill = ColorRGBa.WHITE
stroke = null
rectangle(Rectangle.fromCenter(bounds.position(0.33, 0.5),
150.0, 150.0))
translate(bounds.position(0.62, 0.5))
rotate(30.0)
rectangle(Rectangle.fromCenter(Vector2.ZERO, 200.0, 200.0))
rectangle(0.0, -200.0, 60.0, 60.0)
circle(0.0, 190.0, 60.0)
}
// Convert the bitmap buffer into ShapeContours
val vectorized = imageToContours(rt.colorBuffer(0))
fun main() = application {
program {
// Create a buffer where to draw something for boofcv
val rt = renderTarget(width, height) {
colorBuffer()
depthBuffer()
}
// Draw some shapes on that buffer
drawer.isolatedWithTarget(rt) {
clear(ColorRGBa.BLACK)
fill = ColorRGBa.WHITE
stroke = null
rectangle(
Rectangle.fromCenter(
bounds.position(0.33, 0.5),
150.0, 150.0
)
)
translate(bounds.position(0.62, 0.5))
rotate(30.0)
rectangle(Rectangle.fromCenter(Vector2.ZERO, 200.0, 200.0))
rectangle(0.0, -200.0, 60.0, 60.0)
circle(0.0, 190.0, 60.0)
}
// Convert the bitmap buffer into ShapeContours
val vectorized = imageToContours(rt.colorBuffer(0))
// Show amount of segments in each shape (high number)
vectorized.forEachIndexed { i, it ->
println("boofcv shape $i: ${it.segments.size} segments")
}
// Show amount of segments in each shape (high number)
vectorized.forEachIndexed { i, it ->
println("boofcv shape $i: ${it.segments.size} segments")
}
// Make a simplified list of points
val simplePoints = vectorized.map {
simplify(it.adaptivePositions(), 4.0)
}.filter { it.size >= 3 }
// Make a simplified list of points
val simplePoints = vectorized.map {
simplify(it.adaptivePositions(), 4.0)
}.filter { it.size >= 3 }
// Use the simplified list to make a smooth contour
val smooth = simplePoints.map {
CatmullRomChain2(it, 0.0, true).toContour()
}
// Use the simplified list to make a smooth contour
val smooth = simplePoints.map {
CatmullRomChain2(it, 0.0, true).toContour()
}
// Use the simplified list to make a polygonal contour
val polygonal = simplePoints.map {
ShapeContour.fromPoints(it, true)
}
// Use the simplified list to make a polygonal contour
val polygonal = simplePoints.map {
ShapeContour.fromPoints(it, true)
}
// Show amount of segments in simplified shapes (low number).
// Note: `smooth` and `polygonal` have the same number of segments
smooth.forEachIndexed { i, it ->
println("simplified shape $i: ${it.segments.size} segments")
}
// Show amount of segments in simplified shapes (low number).
// Note: `smooth` and `polygonal` have the same number of segments
smooth.forEachIndexed { i, it ->
println("simplified shape $i: ${it.segments.size} segments")
}
extend {
drawer.run {
fill = null // ColorRGBa.PINK.opacify(0.15)
stroke = ColorRGBa.PINK.opacify(0.7)
contours(polygonal)
contours(smooth)
}
extend {
drawer.run {
fill = null // ColorRGBa.PINK.opacify(0.15)
stroke = ColorRGBa.PINK.opacify(0.7)
contours(polygonal)
contours(smooth)
}
}
}
@@ -97,4 +99,4 @@ fun imageToContours(input: ColorBuffer): List<ShapeContour> {
// orx-boofcv: convert vector data to OPENRNDR ShapeContours
return contours.toShapeContours(true, internal = true, external = true)
}
}

View File

@@ -62,7 +62,7 @@ private fun SceneRenderer.processVoxelConeTracing(drawer: Drawer, scene: Scene,
val position = Vector3.ZERO
drawer.lookAt(position + side.forward*40.0, position , side.up)
drawPass(drawer, pass, materialContext, context) {
it.parameter("voxelMap", feature.voxelMap!!.imageBinding(0, ImageAccess.WRITE))
it.image("voxelMap", feature.voxelMap!!.imageBinding(0, ImageAccess.WRITE))
}
}
}

View File

@@ -4,25 +4,23 @@ import org.openrndr.extra.parameters.Description
import org.openrndr.extra.parameters.PathParameter
import org.openrndr.extra.propertywatchers.watchingImagePath
fun main() {
application {
program {
val gui = GUI()
gui.compartmentsCollapsedByDefault = false
fun main() = application {
program {
val gui = GUI()
gui.compartmentsCollapsedByDefault = false
val settings = @Description("Settings") object {
@PathParameter("image", extensions = ["jpg", "png"], order = 10)
var imagePath = "demo-data/images/image-001.png"
val settings = @Description("Settings") object {
@PathParameter("image", extensions = ["jpg", "png"], order = 10)
var imagePath = "demo-data/images/image-001.png"
val image by watchingImagePath(::imagePath) {
it
}
}
gui.add(settings)
extend(gui)
extend {
drawer.image(settings.image)
val image by watchingImagePath(::imagePath) {
it
}
}
gui.add(settings)
extend(gui)
extend {
drawer.image(settings.image)
}
}
}
}

View File

@@ -8,7 +8,6 @@ import org.openrndr.*
import org.openrndr.color.ColorRGBa
import org.openrndr.dialogs.*
import org.openrndr.draw.Drawer
import org.openrndr.extra.noise.random
import org.openrndr.extra.noise.uniform
import org.openrndr.extra.parameters.*
import org.openrndr.internal.Driver
@@ -1077,7 +1076,7 @@ open class GUI(
val min = parameter.doubleRange!!.start
val max = parameter.doubleRange!!.endInclusive
val currentValue = (parameter.property as KMutableProperty1<Any, Double>).get(labeledObject.obj)
val randomValue = random(min, max)
val randomValue = Double.uniform(min, max)
val newValue = mix(currentValue, randomValue, strength)
(parameter.property as KMutableProperty1<Any, Double>).set(labeledObject.obj, newValue)
}
@@ -1086,7 +1085,7 @@ open class GUI(
val min = parameter.intRange!!.first
val max = parameter.intRange!!.last
val currentValue = (parameter.property as KMutableProperty1<Any, Int>).get(labeledObject.obj)
val randomValue = random(min.toDouble(), max.toDouble())
val randomValue = Double.uniform(min.toDouble(), max.toDouble())
val newValue = mix(currentValue.toDouble(), randomValue, strength).roundToInt()
(parameter.property as KMutableProperty1<Any, Int>).set(labeledObject.obj, newValue)
}

View File

@@ -9,33 +9,31 @@ import org.openrndr.math.Vector2
/**
* Demonstration of two-way binding using [bindMidiControl]
*/
fun main() {
application {
program {
val midi = openMidiDevice("MIDI2x2 [hw:3,0,0]")
val settings = object {
@DoubleParameter("radius", 0.0, 100.0)
var radius = 0.0
fun main() = application {
program {
val midi = openMidiDevice("MIDI2x2 [hw:3,0,0]")
val settings = object {
@DoubleParameter("radius", 0.0, 100.0)
var radius = 0.0
@DoubleParameter("x", -100.0, 100.0)
var x = 0.0
@DoubleParameter("x", -100.0, 100.0)
var x = 0.0
@DoubleParameter("y", -100.0, 100.0)
var y = 0.0
@DoubleParameter("y", -100.0, 100.0)
var y = 0.0
@ColorParameter("fill")
var color = ColorRGBa.WHITE
}
@ColorParameter("fill")
var color = ColorRGBa.WHITE
}
bindMidiControl(settings::radius, midi, 0, 1)
bindMidiControl(settings::x, midi, 0, 2)
bindMidiControl(settings::y, midi, 0, 3)
bindMidiControl(settings::color, midi, 0, 4)
bindMidiControl(settings::radius, midi, 0, 1)
bindMidiControl(settings::x, midi, 0, 2)
bindMidiControl(settings::y, midi, 0, 3)
bindMidiControl(settings::color, midi, 0, 4)
extend {
drawer.fill = settings.color
drawer.circle(drawer.bounds.center + Vector2(settings.x, settings.y), settings.radius)
}
extend {
drawer.fill = settings.color
drawer.circle(drawer.bounds.center + Vector2(settings.x, settings.y), settings.radius)
}
}
}
}

View File

@@ -6,14 +6,12 @@ import org.openrndr.extra.midi.openMidiDevice
/**
* Demonstration of [MidiConsole]
*/
fun main() {
application {
program {
listMidiDevices().forEach { println(it.toString()) }
val midi = openMidiDevice("Launchpad [hw:4,0,0]")
extend(MidiConsole()) {
register(midi)
}
fun main() = application {
program {
listMidiDevices().forEach { println(it.toString()) }
val midi = openMidiDevice("Launchpad [hw:4,0,0]")
extend(MidiConsole()) {
register(midi)
}
}
}
}

View File

@@ -13,98 +13,96 @@ import kotlin.random.Random
* Hold the mouse button to randomize the frequencies.
* Press keys 'a' or 'b' for less random frequencies.
*/
fun main() {
application {
program {
val minim = minim()
val out = minim.lineOut
fun main() = application {
program {
val minim = minim()
val out = minim.lineOut
if (out == null) {
application.exit()
if (out == null) {
application.exit()
}
// generates a random frequency value biased down
fun randomFreq() = 20f + Random.nextFloat().pow(3) * 1000
// If one didn't want to visualize or control the synths we
// wouldn't need a data structure to store them. Here we store
// Pairs, so we have access both to the frequency of the wave
// and the current amplitude defined by the lfo (low frequency
// oscillator).
val synths = List(20) {
// By default, Oscil creates sine waves, but it can be changed.
val lfo = Oscil(
Random.nextFloat() * 0.1f + 0.005f,
0.05f
).apply {
// Here we set the center of the lfo to 0.05f.
// Since the amplitude is also 0.05f, it moves between
// 0.00f and 0.10f.
offset.lastValue = 0.05f
// Have the sine waves to not start in sync.
//phase.lastValue = Random.nextFloat() * 6.28f
}
val wave = Oscil(randomFreq(), 0f)
// The `lfo` Oscil controls the `wave` Oscil's amplitude.
lfo.patch(wave.amplitude)
// Random pan to avoid a mono sound.
val pan = Pan(Random.nextFloat() * 2 - 1)
wave.patch(pan)
pan.patch(out)
// Store a [Pair] in `synths`.
Pair(wave, lfo)
}
val bgColor = rgb(0.094, 0.188, 0.349)
val lineColor = rgb(0.992, 0.918, 0.671)
val mouseTracker = MouseTracker(mouse)
// generates a random frequency value biased down
fun randomFreq() = 20f + Random.nextFloat().pow(3) * 1000
// If one didn't want to visualize or control the synths we
// wouldn't need a data structure to store them. Here we store
// Pairs, so we have access both to the frequency of the wave
// and the current amplitude defined by the lfo (low frequency
// oscillator).
val synths = List(20) {
// By default, Oscil creates sine waves, but it can be changed.
val lfo = Oscil(
Random.nextFloat() * 0.1f + 0.005f,
0.05f
).apply {
// Here we set the center of the lfo to 0.05f.
// Since the amplitude is also 0.05f, it moves between
// 0.00f and 0.10f.
offset.lastValue = 0.05f
// Have the sine waves to not start in sync.
//phase.lastValue = Random.nextFloat() * 6.28f
extend {
drawer.clear(bgColor)
drawer.translate(drawer.bounds.center)
drawer.rotate(seconds)
// A CircleBatchBuilder for faster drawing of circles.
drawer.circles {
// For each synth draw a circle.
synths.forEachIndexed { i, (wave, lfo) ->
stroke = lineColor.opacify(Random.nextDouble(0.4) + 0.6)
fill = lineColor.opacify(Random.nextDouble() * 0.04)
// A Polar arrangement centered on the screen.
// Higher pitch circles are farther away from the center.
val pos = Polar(
360.0 * i / synths.size,
50.0 + wave.frequency.lastValue * 0.2
).cartesian
// The size of the circle depends on the current volume
// set by the lfo.
circle(pos, 500 * lfo.lastValues.last().toDouble())
}
val wave = Oscil(randomFreq(), 0f)
// The `lfo` Oscil controls the `wave` Oscil's amplitude.
lfo.patch(wave.amplitude)
// Random pan to avoid a mono sound.
val pan = Pan(Random.nextFloat() * 2 - 1)
wave.patch(pan)
pan.patch(out)
// Store a [Pair] in `synths`.
Pair(wave, lfo)
}
val bgColor = rgb(0.094, 0.188, 0.349)
val lineColor = rgb(0.992, 0.918, 0.671)
val mouseTracker = MouseTracker(mouse)
extend {
drawer.clear(bgColor)
drawer.translate(drawer.bounds.center)
drawer.rotate(seconds)
// A CircleBatchBuilder for faster drawing of circles.
drawer.circles {
// For each synth draw a circle.
synths.forEachIndexed { i, (wave, lfo) ->
stroke = lineColor.opacify(Random.nextDouble(0.4) + 0.6)
fill = lineColor.opacify(Random.nextDouble() * 0.04)
// A Polar arrangement centered on the screen.
// Higher pitch circles are farther away from the center.
val pos = Polar(
360.0 * i / synths.size,
50.0 + wave.frequency.lastValue * 0.2
).cartesian
// The size of the circle depends on the current volume
// set by the lfo.
circle(pos, 500 * lfo.lastValues.last().toDouble())
if (mouseTracker.pressedButtons.isNotEmpty()) {
synths.random().first.setFrequency(randomFreq())
}
}
keyboard.keyDown.listen { key ->
when (key.name) {
"a" -> {
// make all frequencies close to a base frequency
// (circular arrangement)
val baseFreq = 20 + Random.nextFloat() * 200
synths.forEach {
it.first.setFrequency(baseFreq + Random.nextFloat() * 20)
}
}
if (mouseTracker.pressedButtons.isNotEmpty()) {
synths.random().first.setFrequency(randomFreq())
}
}
keyboard.keyDown.listen { key ->
when (key.name) {
"a" -> {
// make all frequencies close to a base frequency
// (circular arrangement)
val baseFreq = 20 + Random.nextFloat() * 200
synths.forEach {
it.first.setFrequency(baseFreq + Random.nextFloat() * 20)
}
}
"b" -> {
// make all frequencies follow an exponential series
// (spiral arrangement)
val inc = Random.nextFloat() * 0.1f
synths.forEachIndexed { i, (wave, _) ->
wave.setFrequency(25f.pow(1f + i * inc))
}
"b" -> {
// make all frequencies follow an exponential series
// (spiral arrangement)
val inc = Random.nextFloat() * 0.1f
synths.forEachIndexed { i, (wave, _) ->
wave.setFrequency(25f.pow(1f + i * inc))
}
}
}
}
}
}
}

View File

@@ -1,38 +1,35 @@
import ddf.minim.Minim
import ddf.minim.analysis.FFT
import ddf.minim.analysis.LanczosWindow
import org.openrndr.application
import org.openrndr.extra.minim.minim
import org.openrndr.math.map
import kotlin.math.ln
fun main() {
application {
configure {
width = 1280
height = 720
fun main() = application {
configure {
width = 1280
height = 720
}
program {
val minim = minim()
if (minim.lineOut == null) {
application.exit()
}
program {
val minim = minim()
if (minim.lineOut == null) {
application.exit()
}
val lineIn = minim.getLineIn(Minim.MONO, 2048, 48000f)
if (lineIn == null) {
application.exit()
}
val fft = FFT(lineIn.bufferSize(), lineIn.sampleRate())
fft.window(LanczosWindow())
extend {
fft.forward(lineIn.mix)
for (i in 0 until 200) {
val bandDB = 20.0 * ln(2.0 * fft.getBand(i) / fft.timeSize())
drawer.rectangle(i * 5.0, height / 2.0, 5.0, bandDB.map(0.0, -150.0, 0.0, -height / 8.0))
}
val lineIn = minim.getLineIn(Minim.MONO, 2048, 48000f)
if (lineIn == null) {
application.exit()
}
val fft = FFT(lineIn.bufferSize(), lineIn.sampleRate())
fft.window(LanczosWindow())
extend {
fft.forward(lineIn.mix)
for (i in 0 until 200) {
val bandDB = 20.0 * ln(2.0 * fft.getBand(i) / fft.timeSize())
drawer.rectangle(i * 5.0, height / 2.0, 5.0, bandDB.map(0.0, -150.0, 0.0, -height / 8.0))
}
}
}
}
}

View File

@@ -1,28 +1,26 @@
import org.openrndr.application
import org.openrndr.extra.minim.minim
fun main() {
application {
program {
val minim = minim()
if (minim.lineOut == null) {
application.exit()
}
fun main() = application {
program {
val minim = minim()
if (minim.lineOut == null) {
application.exit()
}
val player = minim.loadFile(
"demo-data/sounds/26777__junggle__btn402.mp3"
)
val player = minim.loadFile(
"demo-data/sounds/26777__junggle__btn402.mp3"
)
// fade gain to -40dB in 15 seconds
player.shiftGain(player.gain, -40f, 15000)
// fade gain to -40dB in 15 seconds
player.shiftGain(player.gain, -40f, 15000)
extend {
if(frameCount % 30 == 0) {
player.rewind()
//player.gain = Random.nextDouble(-20.0, 0.0).toFloat()
player.play()
}
extend {
if (frameCount % 30 == 0) {
player.rewind()
//player.gain = Random.nextDouble(-20.0, 0.0).toFloat()
player.play()
}
}
}
}
}

View File

@@ -8,39 +8,37 @@ import kotlin.math.cos
/**
* Live-coding with [oliveProgram]
*/
fun main() {
application {
configure {
width = 1280
height = 720
}
oliveProgram {
extend {
drawer.clear(ColorRGBa.PINK)
drawer.fill = ColorRGBa.WHITE
for (i in 0 until 100) {
drawer.circle(
width / 2.0 + cos(seconds + i) * 320.0,
i * 7.2,
cos(i + seconds * 0.5) * 20.0 + 20.0
)
}
}
}
// -- this is only needed for the automated screenshots
.olive.scriptLoaded.listen {
if (System.getProperty("takeScreenshot") == "true") {
// -- this is a bit of hack, we need to push the screenshot extension in front of the olive one
fun <T : Extension> extendHead(extension: T, configure: T.() -> Unit): T {
program.extensions.add(0, extension)
extension.configure()
extension.setup(program)
return extension
}
extendHead(SingleScreenshot()) {
this.outputFile = System.getProperty("screenshotPath")
}
}
}
fun main() = application {
configure {
width = 1280
height = 720
}
}
oliveProgram {
extend {
drawer.clear(ColorRGBa.PINK)
drawer.fill = ColorRGBa.WHITE
for (i in 0 until 100) {
drawer.circle(
width / 2.0 + cos(seconds + i) * 320.0,
i * 7.2,
cos(i + seconds * 0.5) * 20.0 + 20.0
)
}
}
}
// -- this is only needed for the automated screenshots
.olive.scriptLoaded.listen {
if (System.getProperty("takeScreenshot") == "true") {
// -- this is a bit of hack, we need to push the screenshot extension in front of the olive one
fun <T : Extension> extendHead(extension: T, configure: T.() -> Unit): T {
program.extensions.add(0, extension)
extension.configure()
extension.setup(program)
return extension
}
extendHead(SingleScreenshot()) {
this.outputFile = System.getProperty("screenshotPath")
}
}
}
}

View File

@@ -9,6 +9,7 @@ import org.openrndr.draw.colorBuffer
import org.openrndr.draw.isolatedWithTarget
import org.openrndr.draw.renderTarget
import org.openrndr.extra.noise.Random
import org.openrndr.extra.noise.uniform
import org.openrndr.math.Polar
import org.openrndr.math.clamp
import org.openrndr.poissonfill.PoissonFill
@@ -34,11 +35,11 @@ fun main() {
val things = List(10) {
Thing(
ColorHSVa(it * 182.0,
Random.double(0.3, 0.6),
Random.double(0.1, 0.9)).toRGBa(),
Polar(Random.double0(360.0),
Double.uniform(0.3, 0.6),
Double.uniform(0.1, 0.9)).toRGBa(),
Polar(Double.uniform(0.0, 360.0),
100.0 + it * 10.0),
Polar(Random.double(-1.0, 1.0), 0.0))
Polar(Double.uniform(-1.0, 1.0), 0.0))
}
val mouseTracker = MouseTracker(mouse)

View File

@@ -6,29 +6,27 @@ import org.openrndr.draw.colorBuffer
import org.openrndr.draw.tint
import org.openrndr.extra.realsense2.RS2Sensor
fun main() {
application {
program {
val sensors = RS2Sensor.listSensors()
val depthFrame = colorBuffer(640, 480, format = ColorFormat.R, type = ColorType.UINT16)
for (sensor in sensors) {
println(sensor)
}
val sensor = RS2Sensor.openFirstOrDummy()
fun main() = application {
program {
val sensors = RS2Sensor.listSensors()
val depthFrame = colorBuffer(640, 480, format = ColorFormat.R, type = ColorType.UINT16)
for (sensor in sensors) {
println(sensor)
for (stream in sensor.streams) {
println(stream.intrinsics)
}
}
val sensor = RS2Sensor.openFirstOrDummy()
println(sensor)
for (stream in sensor.streams) {
println(stream.intrinsics)
}
sensor.depthFrameReceived.listen {
it.copyTo(depthFrame)
}
extend {
sensor.waitForFrames()
drawer.drawStyle.colorMatrix = tint(ColorRGBa.WHITE.shade(20.0))
drawer.image(depthFrame)
}
sensor.depthFrameReceived.listen {
it.copyTo(depthFrame)
}
extend {
sensor.waitForFrames()
drawer.drawStyle.colorMatrix = tint(ColorRGBa.WHITE.shade(20.0))
drawer.image(depthFrame)
}
}
}
}

View File

@@ -11,35 +11,33 @@ import org.openrndr.extra.realsense2.RS2Sensor
*
* Tested with two sensors, only uses depth stream now
*/
fun main() {
application {
configure {
width = 1280
height = 720
fun main() = application {
configure {
width = 1280
height = 720
}
program {
val sensorDescriptions = RS2Sensor.listSensors()
val sensors = sensorDescriptions.map {
it.open()
}
program {
val sensorDescriptions = RS2Sensor.listSensors()
val sensors = sensorDescriptions.map {
it.open()
val depthFrames = sensors.map {
colorBuffer(640, 480, format = ColorFormat.R, type = ColorType.UINT16)
}
sensors.forEachIndexed { index, it ->
it.depthFrameReceived.listen {
it.copyTo(depthFrames[index])
}
val depthFrames = sensors.map {
colorBuffer(640, 480, format = ColorFormat.R, type = ColorType.UINT16)
}
sensors.forEachIndexed { index, it ->
it.depthFrameReceived.listen {
it.copyTo(depthFrames[index])
}
}
extend {
drawer.drawStyle.colorMatrix = tint(ColorRGBa.WHITE.shade(20.0))
for ((index, sensor) in sensors.withIndex()) {
sensor.waitForFrames()
drawer.image(depthFrames[index])
drawer.translate(640.0, 0.0)
}
}
extend {
drawer.drawStyle.colorMatrix = tint(ColorRGBa.WHITE.shade(20.0))
for ((index, sensor) in sensors.withIndex()) {
sensor.waitForFrames()
drawer.image(depthFrames[index])
drawer.translate(640.0, 0.0)
}
}
}
}
}

View File

@@ -1,9 +1,7 @@
import org.openrndr.application
fun main() {
application {
program {
fun main() = application {
program {
}
}
}
}

View File

@@ -6,20 +6,13 @@ import org.openrndr.draw.shadeStyle
import org.openrndr.extra.camera.Orbital
import org.openrndr.extra.mesh.IIndexedPolygon
import org.openrndr.extra.mesh.IVertexData
import org.openrndr.extra.mesh.noise.nonuniform
import org.openrndr.extra.mesh.noise.nonuniformHammersley
import org.openrndr.extra.mesh.noise.nonuniformRSeq
import org.openrndr.extra.objloader.loadOBJMeshData
import org.openrndr.extra.mesh.noise.uniform
import org.openrndr.extra.meshgenerators.normals.estimateNormals
import org.openrndr.extra.meshgenerators.sphereMesh
import org.openrndr.math.Spherical
import org.openrndr.extra.objloader.loadOBJMeshData
import org.openrndr.math.Vector3
import java.io.File
import kotlin.math.absoluteValue
import kotlin.math.cos
import kotlin.math.pow
import kotlin.math.sin
import kotlin.random.Random

View File

@@ -6,28 +6,26 @@ import org.openrndr.drawImage
import org.openrndr.extra.propertywatchers.watchingImagePath
import org.openrndr.extra.propertywatchers.watchingProperty
fun main() {
application {
program {
val state = object {
var path = "demo-data/images/image-001.png"
val image by watchingImagePath(::path) {
drawImage(it.width, it.height) {
drawer.drawStyle.colorMatrix = grayscale()
drawer.image(it)
}
}
val redImage by watchingProperty(::image, cleaner = { it.destroy() }) {
drawImage(it.width, it.height) {
drawer.drawStyle.colorMatrix = tint(ColorRGBa.RED)
drawer.image(it)
}
fun main() = application {
program {
val state = object {
var path = "demo-data/images/image-001.png"
val image by watchingImagePath(::path) {
drawImage(it.width, it.height) {
drawer.drawStyle.colorMatrix = grayscale()
drawer.image(it)
}
}
extend {
drawer.image(state.redImage)
val redImage by watchingProperty(::image, cleaner = { it.destroy() }) {
drawImage(it.width, it.height) {
drawer.drawStyle.colorMatrix = tint(ColorRGBa.RED)
drawer.image(it)
}
}
}
extend {
drawer.image(state.redImage)
}
}
}
}

View File

@@ -1,22 +1,20 @@
import org.openrndr.application
import org.openrndr.extra.propertywatchers.watchingProperty
fun main() {
application {
program {
val state = object {
val x by watchingProperty(mouse::position) {
it.x
}
val xx by watchingProperty(::x) {
it * it
}
fun main() = application {
program {
val state = object {
val x by watchingProperty(mouse::position) {
it.x
}
extend {
state.x
val xx by watchingProperty(::x) {
it * it
}
}
extend {
state.x
}
}
}
}

View File

@@ -7,42 +7,40 @@ import org.openrndr.extra.quadtree.Quadtree
import org.openrndr.math.Vector2
import org.openrndr.shape.Rectangle
fun main() {
application {
configure {
width = 800
height = 800
title = "QuadTree"
fun main() = application {
configure {
width = 800
height = 800
title = "QuadTree"
}
program {
val box = Rectangle.fromCenter(Vector2(400.0), 750.0)
val points = (0 until 1_000).map {
Vector2.gaussian(box.center, Vector2(95.0), Random.rnd)
}
program {
val box = Rectangle.fromCenter(Vector2(400.0), 750.0)
val points = (0 until 1_000).map {
Vector2.gaussian(box.center, Vector2(95.0), Random.rnd)
}
val quadTree = Quadtree<Vector2>(box) { it }
val quadTree = Quadtree<Vector2>(box) { it }
for (point in points) {
quadTree.insert(point)
}
for (point in points) {
quadTree.insert(point)
}
val batch = drawer.rectangleBatch {
this.fill = null
this.stroke = ColorRGBa.GRAY
this.strokeWeight = 0.5
quadTree.batch(this)
}
val batch = drawer.rectangleBatch {
this.fill = null
this.stroke = ColorRGBa.GRAY
this.strokeWeight = 0.5
quadTree.batch(this)
}
extend {
drawer.clear(ColorRGBa.BLACK)
extend {
drawer.clear(ColorRGBa.BLACK)
drawer.rectangles(batch)
drawer.rectangles(batch)
drawer.fill = ColorRGBa.PINK.opacify(0.7)
drawer.stroke = null
drawer.circles(points, 5.0)
}
drawer.fill = ColorRGBa.PINK.opacify(0.7)
drawer.stroke = null
drawer.circles(points, 5.0)
}
}
}
}

View File

@@ -7,69 +7,67 @@ import org.openrndr.extra.quadtree.Quadtree
import org.openrndr.math.Vector2
import org.openrndr.shape.Rectangle
fun main() {
application {
configure {
width = 800
height = 800
title = "QuadTree"
fun main() = application {
configure {
width = 800
height = 800
title = "QuadTree"
}
program {
val box = Rectangle.fromCenter(Vector2(400.0), 750.0)
val points = (0 until 100).map {
Vector2.gaussian(box.center, Vector2(95.0), Random.rnd)
}
program {
val box = Rectangle.fromCenter(Vector2(400.0), 750.0)
val points = (0 until 100).map {
Vector2.gaussian(box.center, Vector2(95.0), Random.rnd)
}
val quadTree = Quadtree<Vector2>(box) { it }
val quadTree = Quadtree<Vector2>(box) { it }
for (point in points) {
quadTree.insert(point)
}
for (point in points) {
quadTree.insert(point)
}
val selected = points[3]
val radius = 40.0
val selected = points[3]
val radius = 40.0
val nearestQuery = quadTree.nearest(selected, radius)
val nearestQuery = quadTree.nearest(selected, radius)
val batch = drawer.rectangleBatch {
this.fill = null
this.stroke = ColorRGBa.GRAY
this.strokeWeight = 0.5
quadTree.batch(this)
}
val batch = drawer.rectangleBatch {
this.fill = null
this.stroke = ColorRGBa.GRAY
this.strokeWeight = 0.5
quadTree.batch(this)
}
extend {
drawer.clear(ColorRGBa.BLACK)
extend {
drawer.clear(ColorRGBa.BLACK)
drawer.rectangles(batch)
drawer.rectangles(batch)
drawer.fill = ColorRGBa.PINK.opacify(0.7)
drawer.stroke = null
drawer.circles(points, 5.0)
drawer.fill = ColorRGBa.PINK.opacify(0.7)
nearestQuery?.let { (nearest, neighbours, nodes) ->
drawer.stroke = null
drawer.circles(points, 5.0)
drawer.fill = ColorRGBa.YELLOW.opacify(0.2)
nearestQuery?.let { (nearest, neighbours, nodes) ->
drawer.stroke = null
drawer.fill = ColorRGBa.YELLOW.opacify(0.2)
for (node in nodes) {
node.draw(drawer)
}
drawer.fill = ColorRGBa.GREEN.opacify(0.7)
drawer.circles(neighbours, 5.0)
drawer.fill = ColorRGBa.RED.opacify(0.9)
drawer.circle(nearest, 5.0)
drawer.fill = ColorRGBa.PINK
drawer.circle(selected, 5.0)
drawer.stroke = ColorRGBa.PINK
drawer.fill = null
drawer.circle(selected, radius)
for (node in nodes) {
node.draw(drawer)
}
drawer.fill = ColorRGBa.GREEN.opacify(0.7)
drawer.circles(neighbours, 5.0)
drawer.fill = ColorRGBa.RED.opacify(0.9)
drawer.circle(nearest, 5.0)
drawer.fill = ColorRGBa.PINK
drawer.circle(selected, 5.0)
drawer.stroke = ColorRGBa.PINK
drawer.fill = null
drawer.circle(selected, radius)
}
}
}
}
}

View File

@@ -9,77 +9,81 @@ import org.openrndr.shape.Rectangle
* Example of 5 gradient styles.
* NPointLinear and NPoingGradient have separate demos.
*/
fun main() {
application {
configure {
width = 1000
height = 500
}
program {
// Create gradients with initial colors
val gradients = listOf(
RadialGradient(ColorRGBa.PINK, ColorRGBa.WHITE),
AngularGradient(ColorRGBa.PINK, ColorRGBa.WHITE),
NPointGradient(Array(4) {
ColorRGBa.PINK.shade(it / 3.0)
}),
LinearGradient(ColorRGBa.PINK, ColorRGBa.WHITE),
HalfAngularGradient(ColorRGBa.PINK, ColorRGBa.WHITE)
)
fun main() = application {
configure {
width = 1000
height = 500
}
program {
// Create gradients with initial colors
val gradients = listOf(
RadialGradient(ColorRGBa.PINK, ColorRGBa.WHITE),
AngularGradient(ColorRGBa.PINK, ColorRGBa.WHITE),
NPointGradient(Array(4) {
ColorRGBa.PINK.shade(it / 3.0)
}),
LinearGradient(ColorRGBa.PINK, ColorRGBa.WHITE),
HalfAngularGradient(ColorRGBa.PINK, ColorRGBa.WHITE)
)
extend {
gradients.forEachIndexed { gradientId, gradient ->
for (column in 0 until 10) {
val color1 = ColorRGBa.PINK.toHSVa().shiftHue(column * 12.0)
.shade(0.5).toRGBa()
extend {
gradients.forEachIndexed { gradientId, gradient ->
for (column in 0 until 10) {
val color1 = ColorRGBa.PINK.toHSVa().shiftHue(column * 12.0)
.shade(0.5).toRGBa()
val w = width.toDouble() / 10.0
val h = height.toDouble() / gradients.size
val rect = Rectangle(column * w, gradientId * h, w, h)
val w = width.toDouble() / 10.0
val h = height.toDouble() / gradients.size
val rect = Rectangle(column * w, gradientId * h, w, h)
val offset = Polar((seconds + column) * 15.0, 0.3).cartesian
val offset = Polar((seconds + column) * 15.0, 0.3).cartesian
drawer.isolated {
when (gradient) {
is RadialGradient -> {
gradient.color1 = color1
gradient.exponent = column / 3.0 + 0.3
gradient.length = 0.6
gradient.offset = offset
}
is AngularGradient -> {
gradient.color1 = color1
gradient.exponent = column / 3.0 + 0.3
gradient.rotation = (seconds - column) * 10.0
gradient.offset = offset
}
is LinearGradient -> {
gradient.color1 = color1
gradient.exponent = column / 3.0 + 0.3
gradient.rotation = seconds * 10.0
}
is HalfAngularGradient -> {
gradient.color1 = color1
gradient.exponent = column / 3.0 + 0.3
gradient.rotation = (column - seconds) * 10.0
gradient.offset = offset
}
is NPointGradient -> {
// Animate points.
// We could also animate colors.
gradient.points = Array(gradient.colors.size) {
rect.center + Polar(it * 90.0 +
drawer.isolated {
when (gradient) {
is RadialGradient -> {
gradient.color1 = color1
gradient.exponent = column / 3.0 + 0.3
gradient.length = 0.6
gradient.offset = offset
}
is AngularGradient -> {
gradient.color1 = color1
gradient.exponent = column / 3.0 + 0.3
gradient.rotation = (seconds - column) * 10.0
gradient.offset = offset
}
is LinearGradient -> {
gradient.color1 = color1
gradient.exponent = column / 3.0 + 0.3
gradient.rotation = seconds * 10.0
}
is HalfAngularGradient -> {
gradient.color1 = color1
gradient.exponent = column / 3.0 + 0.3
gradient.rotation = (column - seconds) * 10.0
gradient.offset = offset
}
is NPointGradient -> {
// Animate points.
// We could also animate colors.
gradient.points = Array(gradient.colors.size) {
rect.center + Polar(
it * 90.0 +
column * 36 - seconds * 10,
40.0).cartesian
}
40.0
).cartesian
}
}
shadeStyle = gradient
rectangle(rect)
}
shadeStyle = gradient
rectangle(rect)
}
}
}
}
}
}
}

View File

@@ -3,23 +3,21 @@ import org.openrndr.color.ColorRGBa
import org.openrndr.extra.color.spaces.toOKLABa
import org.openrndr.extra.shadestyles.linearGradient
fun main() {
application {
program {
extend {
drawer.shadeStyle = linearGradient(
ColorRGBa.RED.toOKLABa(),
ColorRGBa.BLUE.toOKLABa(),
)
drawer.rectangle(120.0, 40.0, 200.0, 400.0)
fun main() = application {
program {
extend {
drawer.shadeStyle = linearGradient(
ColorRGBa.RED.toOKLABa(),
ColorRGBa.BLUE.toOKLABa(),
)
drawer.rectangle(120.0, 40.0, 200.0, 400.0)
drawer.shadeStyle = linearGradient(
ColorRGBa.RED,
ColorRGBa.BLUE
)
drawer.shadeStyle = linearGradient(
ColorRGBa.RED,
ColorRGBa.BLUE
)
drawer.rectangle(120.0+200.0, 40.0, 200.0, 400.0)
}
drawer.rectangle(120.0 + 200.0, 40.0, 200.0, 400.0)
}
}
}
}

View File

@@ -16,31 +16,29 @@ import kotlin.math.cos
* on a static shape (a circle for example) or you can animate a shape
* with a static gradient.
*/
fun main() {
application {
program {
val numPoints = 8
val gradient = NPointGradient(Array(numPoints) {
ColorXSVa(it * 360.0 / numPoints, 1.0, 1.0).toRGBa()
})
fun main() = application {
program {
val numPoints = 8
val gradient = NPointGradient(Array(numPoints) {
ColorXSVa(it * 360.0 / numPoints, 1.0, 1.0).toRGBa()
})
extend {
drawer.run {
clear(ColorRGBa.WHITE.shade(0.9))
val t = PI * 2 * (frameCount % 300) / 300.0
val points = Array(numPoints) {
val lfo = cos(it * PI / 2 - t)
val theta = it * 360.0 / numPoints - 22.5 * lfo
val radius = 200 + 170 * lfo
bounds.center + Polar(theta, radius).cartesian
}
gradient.points = points
shadeStyle = gradient
stroke = ColorRGBa.WHITE
strokeWeight = 4.0
contour(ShapeContour.fromPoints(points.asList(), true))
extend {
drawer.run {
clear(ColorRGBa.WHITE.shade(0.9))
val t = PI * 2 * (frameCount % 300) / 300.0
val points = Array(numPoints) {
val lfo = cos(it * PI / 2 - t)
val theta = it * 360.0 / numPoints - 22.5 * lfo
val radius = 200 + 170 * lfo
bounds.center + Polar(theta, radius).cartesian
}
gradient.points = points
shadeStyle = gradient
stroke = ColorRGBa.WHITE
strokeWeight = 4.0
contour(ShapeContour.fromPoints(points.asList(), true))
}
}
}
}
}

View File

@@ -15,52 +15,50 @@ import kotlin.math.sin
* uniformly between 0.0 and 1.0 and then animated towards one of
* the ends over time using pow() and sin(seconds).
*/
fun main() {
application {
program {
val numPoints = 8
// Create gradients using two different color spaces
val gradients = listOf(
NPointLinearGradient(Array(numPoints) {
ColorXSVa(it * 360.0 / numPoints, 1.0, 1.0).toRGBa()
}),
// OKLab is better at maintaining luminosity across the gradient
NPointLinearGradientOKLab(Array(numPoints) {
ColorXSVa(it * 360.0 / numPoints, 1.0, 1.0).toRGBa()
.toOKLABa()
})
)
fun main() = application {
program {
val numPoints = 8
// Create gradients using two different color spaces
val gradients = listOf(
NPointLinearGradient(Array(numPoints) {
ColorXSVa(it * 360.0 / numPoints, 1.0, 1.0).toRGBa()
}),
// OKLab is better at maintaining luminosity across the gradient
NPointLinearGradientOKLab(Array(numPoints) {
ColorXSVa(it * 360.0 / numPoints, 1.0, 1.0).toRGBa()
.toOKLABa()
})
)
extend {
// The points should be sorted values between 0.0 and 1.0
val distribution = Array(numPoints) {
// uniform distribution
// (it / (numPoints - 1.0))
extend {
// The points should be sorted values between 0.0 and 1.0
val distribution = Array(numPoints) {
// uniform distribution
// (it / (numPoints - 1.0))
// skewed and animated distribution
(it / (numPoints - 1.0)).pow(1.0 + 0.5 * sin(seconds))
}
drawer.run {
clear(rgb(0.2))
stroke = rgb(0.35)
strokeWeight = 8.0
// skewed and animated distribution
(it / (numPoints - 1.0)).pow(1.0 + 0.5 * sin(seconds))
}
drawer.run {
clear(rgb(0.2))
stroke = rgb(0.35)
strokeWeight = 8.0
gradients.forEachIndexed { i, gradient ->
shadeStyle = gradient
gradient.points = distribution
gradients.forEachIndexed { i, gradient ->
shadeStyle = gradient
gradient.points = distribution
gradient.rotation = seconds * 10
circle(bounds.position(0.34, 0.29 + 0.44 * i), 110.0)
gradient.rotation = seconds * 10
circle(bounds.position(0.34, 0.29 + 0.44 * i), 110.0)
gradient.rotation += 90
rectangle(
Rectangle.fromCenter(
bounds.position(0.655, 0.29 + 0.44 * i), 200.0
)
gradient.rotation += 90
rectangle(
Rectangle.fromCenter(
bounds.position(0.655, 0.29 + 0.44 * i), 200.0
)
}
)
}
}
}
}
}
}

View File

@@ -6,35 +6,37 @@ import org.openrndr.shape.Circle
import kotlin.random.Random
/**
* Demonstrate using a multi color radial gradient.
* Demonstrate using a multicolor radial gradient.
* The gradient has 5 colors (first and last ones are transparent).
* Any of the properties can be animated, including colors and points.
* See DemoNPointLinearGradient01.kt for an example of animated properties.
*/
fun main() {
application {
program {
val gradient = NPointRadialGradient(arrayOf(
ColorRGBa.PINK.opacify(0.0),
ColorRGBa.PINK, ColorRGBa.WHITE, ColorRGBa.PINK,
ColorRGBa.PINK.opacify(0.0)
), arrayOf(0.0, 0.4, 0.5, 0.6, 1.0))
fun main() = application {
program {
val gradient = NPointRadialGradient(
arrayOf(
ColorRGBa.PINK.opacify(0.0),
ColorRGBa.PINK, ColorRGBa.WHITE, ColorRGBa.PINK,
ColorRGBa.PINK.opacify(0.0)
), arrayOf(0.0, 0.4, 0.5, 0.6, 1.0)
)
val circles = List(25) {
Circle(Random.nextDouble() * drawer.width,
Random.nextDouble() * drawer.height,
Random.nextDouble() * 150.0)
}
val circles = List(25) {
Circle(
Random.nextDouble() * drawer.width,
Random.nextDouble() * drawer.height,
Random.nextDouble() * 150.0
)
}
extend {
drawer.run {
clear(rgb(0.2))
shadeStyle = gradient
fill = ColorRGBa.WHITE
stroke = null
circles(circles)
}
extend {
drawer.run {
clear(rgb(0.2))
shadeStyle = gradient
fill = ColorRGBa.WHITE
stroke = null
circles(circles)
}
}
}
}
}

View File

@@ -3,17 +3,15 @@ import org.openrndr.color.ColorRGBa
import org.openrndr.extra.shadestyles.radialGradient
import kotlin.math.cos
fun main() {
application {
program {
extend {
drawer.shadeStyle = radialGradient(
ColorRGBa.PINK,
ColorRGBa.PINK.toHSVa().shiftHue(180.0).shade(0.5).toRGBa(),
exponent = cos(seconds)*0.5+0.5
)
drawer.rectangle(120.0, 40.0, 400.0, 400.0)
}
fun main() = application {
program {
extend {
drawer.shadeStyle = radialGradient(
ColorRGBa.PINK,
ColorRGBa.PINK.toHSVa().shiftHue(180.0).shade(0.5).toRGBa(),
exponent = cos(seconds) * 0.5 + 0.5
)
drawer.rectangle(120.0, 40.0, 400.0, 400.0)
}
}
}
}

View File

@@ -8,28 +8,26 @@ import org.openrndr.shape.Circle
import kotlin.math.cos
import kotlin.math.sin
fun main() {
application {
configure {
width = 800
height = 800
}
program {
extend {
var contour = Circle(drawer.bounds.center, 300.0).contour
contour = adjustContour(contour) {
selectVertex(0)
vertex.moveBy(Vector2(cos(seconds) * 40.0, sin(seconds * 0.43) * 40.0))
fun main() = application {
configure {
width = 800
height = 800
}
program {
extend {
var contour = Circle(drawer.bounds.center, 300.0).contour
contour = adjustContour(contour) {
selectVertex(0)
vertex.moveBy(Vector2(cos(seconds) * 40.0, sin(seconds * 0.43) * 40.0))
selectVertex(2)
vertex.rotate(seconds * 45.0)
selectVertex(2)
vertex.rotate(seconds * 45.0)
selectVertex(1)
vertex.scale(cos(seconds*0.943)*2.0)
}
drawer.stroke = ColorRGBa.RED
drawer.contour(contour)
selectVertex(1)
vertex.scale(cos(seconds * 0.943) * 2.0)
}
drawer.stroke = ColorRGBa.RED
drawer.contour(contour)
}
}
}
}

View File

@@ -8,27 +8,25 @@ import org.openrndr.shape.Circle
import kotlin.math.cos
import kotlin.math.sin
fun main() {
application {
configure {
width = 800
height = 800
}
program {
extend {
var contour = Circle(drawer.bounds.center, 300.0).contour
contour = adjustContour(contour) {
selectVertex(0)
vertex.remove()
selectVertex(0)
vertex.moveBy(Vector2(cos(seconds) * 40.0, sin(seconds * 0.43) * 40.0))
vertex.scale(cos(seconds*2.0)*2.0)
fun main() = application {
configure {
width = 800
height = 800
}
program {
extend {
var contour = Circle(drawer.bounds.center, 300.0).contour
contour = adjustContour(contour) {
selectVertex(0)
vertex.remove()
selectVertex(0)
vertex.moveBy(Vector2(cos(seconds) * 40.0, sin(seconds * 0.43) * 40.0))
vertex.scale(cos(seconds * 2.0) * 2.0)
}
drawer.stroke = ColorRGBa.RED
drawer.contour(contour)
}
drawer.stroke = ColorRGBa.RED
drawer.contour(contour)
}
}
}
}

View File

@@ -7,37 +7,35 @@ import org.openrndr.math.Vector2
import kotlin.math.cos
import kotlin.math.sin
fun main() {
application {
configure {
width = 800
height = 800
}
program {
extend {
var contour = drawer.bounds.scaledBy(0.5, 0.5, 0.5).contour
contour = adjustContour(contour) {
for (i in 0 until 4) {
selectEdge(i)
edge.toCubic()
}
selectEdge(0)
edge.scale(0.5, 0.5)
edge.rotate(cos(seconds*0.5)*30.0)
selectEdge(1)
fun main() = application {
configure {
width = 800
height = 800
}
program {
extend {
var contour = drawer.bounds.scaledBy(0.5, 0.5, 0.5).contour
contour = adjustContour(contour) {
for (i in 0 until 4) {
selectEdge(i)
edge.toCubic()
edge.splitAt(0.5)
edge.moveBy(Vector2(cos(seconds*10.0) * 40.0, 0.0))
//edge.next?.select()
selectEdge(3)
edge.moveBy(Vector2(0.0, sin(seconds*10.0) * 40.0))
}
drawer.stroke = ColorRGBa.RED
drawer.contour(contour)
selectEdge(0)
edge.scale(0.5, 0.5)
edge.rotate(cos(seconds * 0.5) * 30.0)
selectEdge(1)
edge.toCubic()
edge.splitAt(0.5)
edge.moveBy(Vector2(cos(seconds * 10.0) * 40.0, 0.0))
//edge.next?.select()
selectEdge(3)
edge.moveBy(Vector2(0.0, sin(seconds * 10.0) * 40.0))
}
drawer.stroke = ColorRGBa.RED
drawer.contour(contour)
}
}
}
}

View File

@@ -6,26 +6,24 @@ import org.openrndr.extra.shapes.adjust.adjustContour
import org.openrndr.shape.Circle
import kotlin.math.cos
fun main() {
application {
configure {
width = 800
height = 800
}
program {
extend {
var contour = if (seconds.mod(2.0) < 1.0) {
drawer.bounds.scaledBy(0.5, 0.5, 0.5).contour
} else {
Circle(drawer.bounds.center, 300.0).contour
}
contour = adjustContour(contour) {
selectEdge(0)
edge.replaceWith(cos(seconds) * 0.5 + 0.5)
}
drawer.stroke = ColorRGBa.RED
drawer.contour(contour)
fun main() = application {
configure {
width = 800
height = 800
}
program {
extend {
var contour = if (seconds.mod(2.0) < 1.0) {
drawer.bounds.scaledBy(0.5, 0.5, 0.5).contour
} else {
Circle(drawer.bounds.center, 300.0).contour
}
contour = adjustContour(contour) {
selectEdge(0)
edge.replaceWith(cos(seconds) * 0.5 + 0.5)
}
drawer.stroke = ColorRGBa.RED
drawer.contour(contour)
}
}
}
}

View File

@@ -6,31 +6,29 @@ import org.openrndr.extra.shapes.adjust.adjustContour
import org.openrndr.shape.Circle
import kotlin.math.cos
fun main() {
application {
configure {
width = 800
height = 800
}
program {
extend {
var contour =
Circle(drawer.bounds.center, 300.0).contour
fun main() = application {
configure {
width = 800
height = 800
}
program {
extend {
var contour =
Circle(drawer.bounds.center, 300.0).contour
contour = adjustContour(contour) {
selectEdges(0, 1, 2, 3)
edges.forEachIndexed { index, it ->
if (index == seconds.mod(4.0).toInt()) {
it.replaceWith(0.5)
} else {
val v = cos(seconds) * 0.15 + 0.25
it.sub(0.5 - v, 0.5 + v)
}
contour = adjustContour(contour) {
selectEdges(0, 1, 2, 3)
edges.forEachIndexed { index, it ->
if (index == seconds.mod(4.0).toInt()) {
it.replaceWith(0.5)
} else {
val v = cos(seconds) * 0.15 + 0.25
it.sub(0.5 - v, 0.5 + v)
}
}
drawer.stroke = ColorRGBa.RED
drawer.contour(contour)
}
drawer.stroke = ColorRGBa.RED
drawer.contour(contour)
}
}
}
}

View File

@@ -6,38 +6,36 @@ import org.openrndr.extra.shapes.adjust.adjustContour
import org.openrndr.shape.Circle
import kotlin.math.cos
fun main() {
application {
configure {
width = 800
height = 800
}
program {
extend {
var contour =
Circle(drawer.bounds.center, 300.0).contour
fun main() = application {
configure {
width = 800
height = 800
}
program {
extend {
var contour =
Circle(drawer.bounds.center, 300.0).contour
contour = adjustContour(contour) {
parameters.clearSelectedVertices = true
parameters.selectInsertedVertices = true
contour = adjustContour(contour) {
parameters.clearSelectedVertices = true
parameters.selectInsertedVertices = true
for (i in 0 until 4) {
val splitT = cos(seconds + i * Math.PI*0.5)*0.2+0.5
selectEdges { it -> true }
for (e in edges) {
e.splitAt(splitT)
}
// as a resut of the clearSelectedVertices and selectInsertedVertices settings
// the vertex selection is set to the newly inserted vertices
for ((index, v) in vertices.withIndex()) {
v.scale(cos(seconds + i + index) * 0.5 * (1.0 / (1.0 + i)) + 1.0, drawer.bounds.center)
}
for (i in 0 until 4) {
val splitT = cos(seconds + i * Math.PI * 0.5) * 0.2 + 0.5
selectEdges { it -> true }
for (e in edges) {
e.splitAt(splitT)
}
// as a resut of the clearSelectedVertices and selectInsertedVertices settings
// the vertex selection is set to the newly inserted vertices
for ((index, v) in vertices.withIndex()) {
v.scale(cos(seconds + i + index) * 0.5 * (1.0 / (1.0 + i)) + 1.0, drawer.bounds.center)
}
}
drawer.stroke = ColorRGBa.RED
drawer.contour(contour)
}
drawer.stroke = ColorRGBa.RED
drawer.contour(contour)
}
}
}
}

View File

@@ -7,36 +7,34 @@ import org.openrndr.math.Vector2
import org.openrndr.shape.contour
import kotlin.math.cos
fun main() {
application {
configure {
width = 800
height = 800
}
program {
extend {
var contour = contour {
moveTo(drawer.bounds.center - Vector2(300.0, 0.0))
lineTo(drawer.bounds.center + Vector2(300.0, 0.0))
}
contour = adjustContour(contour) {
selectEdge(0)
edge.splitIn(128)
val tr = cos(seconds) * 0.5 + 0.5
selectVertices { i, v -> v.t >= tr }
val anchor = contour.position(tr)
for (v in vertices) {
v.rotate((v.t - tr) * 2000.0, anchor)
v.scale(0.05, anchor)
}
}
drawer.stroke = ColorRGBa.RED
drawer.contour(contour)
fun main() = application {
configure {
width = 800
height = 800
}
program {
extend {
var contour = contour {
moveTo(drawer.bounds.center - Vector2(300.0, 0.0))
lineTo(drawer.bounds.center + Vector2(300.0, 0.0))
}
contour = adjustContour(contour) {
selectEdge(0)
edge.splitIn(128)
val tr = cos(seconds) * 0.5 + 0.5
selectVertices { i, v -> v.t >= tr }
val anchor = contour.position(tr)
for (v in vertices) {
v.rotate((v.t - tr) * 2000.0, anchor)
v.scale(0.05, anchor)
}
}
drawer.stroke = ColorRGBa.RED
drawer.contour(contour)
}
}
}
}

View File

@@ -1,4 +1,4 @@
//package adjust
package adjust
import org.openrndr.application
import org.openrndr.color.ColorRGBa
@@ -6,46 +6,44 @@ import org.openrndr.extra.shapes.adjust.adjustContour
import org.openrndr.math.Vector2
import org.openrndr.shape.contour
fun main() {
application {
configure {
width = 800
height = 800
}
program {
extend {
var contour = contour {
moveTo(drawer.bounds.position(0.5, 0.1) - Vector2(300.0, 0.0))
lineTo(drawer.bounds.position(0.5, 0.1) + Vector2(300.0, 0.0))
}
fun main() = application {
configure {
width = 800
height = 800
}
program {
extend {
var contour = contour {
moveTo(drawer.bounds.position(0.5, 0.1) - Vector2(300.0, 0.0))
lineTo(drawer.bounds.position(0.5, 0.1) + Vector2(300.0, 0.0))
}
contour = adjustContour(contour) {
selectVertex(0)
vertex.moveControlOutBy(Vector2(0.0, 100.0))
contour = adjustContour(contour) {
selectVertex(0)
vertex.moveControlOutBy(Vector2(0.0, 100.0))
selectVertex(1)
vertex.moveControlInBy(Vector2(0.0, -100.0))
}
drawer.stroke = ColorRGBa.RED
drawer.contour(contour)
contour = contour {
moveTo(drawer.bounds.position(0.5, 0.2) - Vector2(300.0, 0.0))
lineTo(drawer.bounds.position(0.5, 0.2) + Vector2(300.0, 0.0))
}
contour = adjustContour(contour) {
selectEdge(0)
edge.moveControl0By(Vector2(0.0, 100.0))
edge.moveControl1By(Vector2(0.0, -100.0))
}
drawer.stroke = ColorRGBa.RED
drawer.contour(contour)
selectVertex(1)
vertex.moveControlInBy(Vector2(0.0, -100.0))
}
drawer.stroke = ColorRGBa.RED
drawer.contour(contour)
contour = contour {
moveTo(drawer.bounds.position(0.5, 0.2) - Vector2(300.0, 0.0))
lineTo(drawer.bounds.position(0.5, 0.2) + Vector2(300.0, 0.0))
}
contour = adjustContour(contour) {
selectEdge(0)
edge.moveControl0By(Vector2(0.0, 100.0))
edge.moveControl1By(Vector2(0.0, -100.0))
}
drawer.stroke = ColorRGBa.RED
drawer.contour(contour)
}
}
}
}

View File

@@ -9,52 +9,50 @@ import org.openrndr.extra.shapes.tunni.tunniLine
import org.openrndr.extra.shapes.tunni.tunniPoint
import kotlin.math.sqrt
fun main() {
application {
configure {
width = 800
height = 800
}
program {
extend {
drawer.clear(ColorRGBa.WHITE)
var contour = drawer.bounds.offsetEdges(-200.0).contour
fun main() = application {
configure {
width = 800
height = 800
}
program {
extend {
drawer.clear(ColorRGBa.WHITE)
var contour = drawer.bounds.offsetEdges(-200.0).contour
drawer.fill = null
drawer.fill = null
contour = adjustContour(contour) {
selectVertices(0, 1)
for (v in vertices) {
v.averageTangents()
v.scale(sqrt(2.0))
v.rotate(45.0)
}
selectVertices(2)
for (v in vertices) {
v.switchTangents()
}
contour = adjustContour(contour) {
selectVertices(0, 1)
for (v in vertices) {
v.averageTangents()
v.scale(sqrt(2.0))
v.rotate(45.0)
}
drawer.stroke = ColorRGBa.BLACK
drawer.contour(contour)
drawer.stroke = ColorRGBa.RED
for (s in contour.segments) {
drawer.lineSegment(s.start, s.cubic.control[0])
drawer.lineSegment(s.end, s.cubic.control[1])
selectVertices(2)
for (v in vertices) {
v.switchTangents()
}
drawer.fill = ColorRGBa.BLACK
drawer.stroke = null
drawer.circles(contour.segments.map { it.start }, 5.0)
}
drawer.stroke = ColorRGBa.BLACK
drawer.contour(contour)
drawer.stroke = ColorRGBa.GRAY
for (s in contour.segments) {
drawer.lineSegment(s.tunniLine)
drawer.fill = ColorRGBa.CYAN
drawer.circle(s.tunniPoint, 5.0)
}
drawer.stroke = ColorRGBa.RED
for (s in contour.segments) {
drawer.lineSegment(s.start, s.cubic.control[0])
drawer.lineSegment(s.end, s.cubic.control[1])
}
drawer.fill = ColorRGBa.BLACK
drawer.stroke = null
drawer.circles(contour.segments.map { it.start }, 5.0)
drawer.stroke = ColorRGBa.GRAY
for (s in contour.segments) {
drawer.lineSegment(s.tunniLine)
drawer.fill = ColorRGBa.CYAN
drawer.circle(s.tunniPoint, 5.0)
}
}
}
}
}

View File

@@ -12,91 +12,89 @@ import org.openrndr.math.Vector2
import org.openrndr.shape.Segment2D
import kotlin.math.cos
fun main() {
application {
configure {
width = 800
height = 800
}
program {
fun main() = application {
configure {
width = 800
height = 800
}
program {
var res = drawer.bounds.offsetEdges(-200.0).contour
var selectedSegments = emptyList<Segment2D>()
var selectedPoints = emptyList<Vector2>()
var res = drawer.bounds.offsetEdges(-200.0).contour
var selectedSegments = emptyList<Segment2D>()
var selectedPoints = emptyList<Vector2>()
val contourSeq = adjustContourSequence(res) {
val contourSeq = adjustContourSequence(res) {
sequence {
for (i in 0 until 1000) {
selectEdges()
selectVertices((i*7).mod(4))
for (v in vertices) {
for (j in 0 until 30) {
v.rotate(45.0/30.0)
yield(status)
}
}
selectVertices((i*3).mod(4))
for (v in vertices) {
yield(status)
}
selectVertices()
selectEdges(i.mod(4))
sequence {
for (i in 0 until 1000) {
selectEdges()
selectVertices((i * 7).mod(4))
for (v in vertices) {
for (j in 0 until 30) {
for (e in edges) {
e.withTunniLine(e.tunniLine.position(0.5) + e.tunniLine.normal * cos(i.toDouble() + e.segmentIndex()) * 50.0/30.0)
yield(status)
}
v.rotate(45.0 / 30.0)
yield(status)
}
}
selectVertices((i * 3).mod(4))
for (v in vertices) {
yield(status)
}
selectVertices()
selectEdges(i.mod(4))
for (j in 0 until 30) {
for (e in edges) {
e.withTunniLine(e.tunniLine.position(0.5) + e.tunniLine.normal * cos(i.toDouble() + e.segmentIndex()) * 50.0 / 30.0)
yield(status)
}
}
}
}
}
launch {
for (i in contourSeq) {
res = i.contour
selectedPoints = i.selectedPoints
selectedSegments = i.selectedSegments
yield()
}
launch {
for (i in contourSeq) {
res = i.contour
selectedPoints = i.selectedPoints
selectedSegments = i.selectedSegments
yield()
}
}
extend {
drawer.clear(ColorRGBa.WHITE)
drawer.stroke = ColorRGBa.BLACK
drawer.contour(res)
drawer.stroke = ColorRGBa.RED
for (s in res.segments) {
drawer.lineSegment(s.start, s.cubic.control[0])
drawer.lineSegment(s.end, s.cubic.control[1])
}
drawer.fill = ColorRGBa.BLACK
drawer.stroke = null
drawer.circles(res.segments.map { it.start }, 5.0)
drawer.stroke = ColorRGBa.GRAY
for (s in res.segments) {
drawer.lineSegment(s.tunniLine)
drawer.fill = ColorRGBa.CYAN
drawer.circle(s.tunniPoint, 5.0)
}
extend {
drawer.clear(ColorRGBa.WHITE)
drawer.stroke = ColorRGBa.BLACK
drawer.contour(res)
drawer.stroke = ColorRGBa.RED
for (s in res.segments) {
drawer.lineSegment(s.start, s.cubic.control[0])
drawer.lineSegment(s.end, s.cubic.control[1])
}
drawer.fill = ColorRGBa.BLACK
drawer.stroke = null
drawer.circles(res.segments.map { it.start }, 5.0)
drawer.stroke = ColorRGBa.GRAY
for (s in res.segments) {
drawer.lineSegment(s.tunniLine)
drawer.fill = ColorRGBa.CYAN
drawer.circle(s.tunniPoint, 5.0)
}
drawer.stroke = ColorRGBa.MAGENTA
drawer.strokeWeight = 3.0
for (s in selectedSegments) {
drawer.segment(s)
}
for (p in selectedPoints) {
drawer.circle(p, 5.0)
}
drawer.stroke = ColorRGBa.MAGENTA
drawer.strokeWeight = 3.0
for (s in selectedSegments) {
drawer.segment(s)
}
for (p in selectedPoints) {
drawer.circle(p, 5.0)
}
}
}
}
}

View File

@@ -12,33 +12,34 @@ import org.openrndr.shape.Circle
import kotlin.math.sqrt
import kotlin.random.Random
fun main() {
application {
program {
val circles = listOf(
Circle(drawer.bounds.center -Vector2(50.0, 0.0), 50.0),
Circle(drawer.bounds.center + Vector2(50.0, 0.0), 50.0),
Circle(drawer.bounds.center + Vector2(0.0, 50.0), 50.0),
Circle(drawer.bounds.center - Vector2(0.0, 50.0), 50.0),
Circle(drawer.bounds.center -Vector2(50.0, 0.0), sqrt(50.0*50.0+50.0*50.0)-49.9),
Circle(drawer.bounds.center +Vector2(50.0, 0.0), sqrt(50.0*50.0+50.0*50.0)-49.9),
Circle(drawer.bounds.center -Vector2(0.0, 50.0), sqrt(50.0*50.0+50.0*50.0)-49.9),
Circle(drawer.bounds.center +Vector2(0.0, 50.0), sqrt(50.0*50.0+50.0*50.0)-49.9),
).shuffled()
fun main() = application {
program {
val circles = listOf(
Circle(drawer.bounds.center - Vector2(50.0, 0.0), 50.0),
Circle(drawer.bounds.center + Vector2(50.0, 0.0), 50.0),
Circle(drawer.bounds.center + Vector2(0.0, 50.0), 50.0),
Circle(drawer.bounds.center - Vector2(0.0, 50.0), 50.0),
Circle(drawer.bounds.center - Vector2(50.0, 0.0), sqrt(50.0 * 50.0 + 50.0 * 50.0) - 49.9),
Circle(drawer.bounds.center + Vector2(50.0, 0.0), sqrt(50.0 * 50.0 + 50.0 * 50.0) - 49.9),
Circle(drawer.bounds.center - Vector2(0.0, 50.0), sqrt(50.0 * 50.0 + 50.0 * 50.0) - 49.9),
Circle(drawer.bounds.center + Vector2(0.0, 50.0), sqrt(50.0 * 50.0 + 50.0 * 50.0) - 49.9),
).shuffled()
val arr = Arrangement(circles)
val arr = Arrangement(circles)
extend {
val r = Random(100)
drawer.stroke = ColorRGBa.WHITE
for (f in arr.boundedFaces) {
drawer.fill =
extend {
val r = Random(100)
drawer.stroke = ColorRGBa.WHITE
for (f in arr.boundedFaces) {
drawer.fill =
rgb(Double.uniform(0.0, 1.0, r), Double.uniform(0.0, 1.0, r), Double.uniform(0.0, 1.0, r)).saturate<OKHSV>(0.25)
drawer.contour(f.contour)
}
rgb(
Double.uniform(0.0, 1.0, r),
Double.uniform(0.0, 1.0, r),
Double.uniform(0.0, 1.0, r)
).saturate<OKHSV>(0.25)
drawer.contour(f.contour)
}
}
}
}
}

View File

@@ -15,42 +15,40 @@ import org.openrndr.shape.ShapeContour
* The created contours are horizontal and vertical in "bezier-patch space" but
* are rendered deformed following the shape of the bezier patch.
*/
fun main() {
application {
configure {
width = 800
height = 800
}
program {
// helper to get screen locations using normalized uv values
fun pos(u: Double, v: Double) = drawer.bounds.position(u, v)
val c0 = LineSegment(pos(0.1, 0.1), pos(0.9, 0.1))
val c1 = LineSegment(pos(0.4, 0.3), pos(0.6, 0.4))
val c2 = LineSegment(pos(0.4, 0.7), pos(0.6, 0.6))
val c3 = LineSegment(pos(0.1, 0.9), pos(0.9, 0.9))
fun main() = application {
configure {
width = 800
height = 800
}
program {
// helper to get screen locations using normalized uv values
fun pos(u: Double, v: Double) = drawer.bounds.position(u, v)
val c0 = LineSegment(pos(0.1, 0.1), pos(0.9, 0.1))
val c1 = LineSegment(pos(0.4, 0.3), pos(0.6, 0.4))
val c2 = LineSegment(pos(0.4, 0.7), pos(0.6, 0.6))
val c3 = LineSegment(pos(0.1, 0.9), pos(0.9, 0.9))
val bp = bezierPatch(c0.segment, c1.segment, c2.segment, c3.segment)
val bpSub = bp.sub(0.1, 0.1, 0.6,0.6)
val bp = bezierPatch(c0.segment, c1.segment, c2.segment, c3.segment)
val bpSub = bp.sub(0.1, 0.1, 0.6, 0.6)
extend {
drawer.clear(ColorRGBa.PINK)
extend {
drawer.clear(ColorRGBa.PINK)
// Show the line segments that form the bezier patch
drawer.stroke = ColorRGBa.YELLOW
drawer.strokeWeight = 5.0
drawer.lineSegments(listOf(c0, c1, c2, c3))
// Show the line segments that form the bezier patch
drawer.stroke = ColorRGBa.YELLOW
drawer.strokeWeight = 5.0
drawer.lineSegments(listOf(c0, c1, c2, c3))
drawer.strokeWeight = 1.0
for (i in 0..50) {
drawer.stroke = ColorRGBa.BLACK
drawer.contour(bp.horizontal(i / 50.0))
drawer.contour(bp.vertical(i / 50.0))
drawer.strokeWeight = 1.0
for (i in 0..50) {
drawer.stroke = ColorRGBa.BLACK
drawer.contour(bp.horizontal(i / 50.0))
drawer.contour(bp.vertical(i / 50.0))
drawer.stroke = ColorRGBa.RED
drawer.contour(bpSub.horizontal(i / 50.0))
drawer.contour(bpSub.vertical(i / 50.0))
}
drawer.stroke = ColorRGBa.RED
drawer.contour(bpSub.horizontal(i / 50.0))
drawer.contour(bpSub.vertical(i / 50.0))
}
}
}
}
}

View File

@@ -15,25 +15,23 @@ import org.openrndr.shape.ShapeContour
* but one can manually create any other 4-segment closed contour
* to use in bezier patches.
*/
fun main() {
application {
configure {
width = 800
height = 800
}
program {
val c = Circle(width / 2.0, height / 2.0, 350.0).contour
val bp = bezierPatch(c)
fun main() = application {
configure {
width = 800
height = 800
}
program {
val c = Circle(width / 2.0, height / 2.0, 350.0).contour
val bp = bezierPatch(c)
extend {
drawer.clear(ColorRGBa.PINK)
drawer.stroke = ColorRGBa.BLACK
extend {
drawer.clear(ColorRGBa.PINK)
drawer.stroke = ColorRGBa.BLACK
for (i in 0..10) {
drawer.contour(bp.horizontal(i / 10.0))
drawer.contour(bp.vertical(i / 10.0))
}
for (i in 0..10) {
drawer.contour(bp.horizontal(i / 10.0))
drawer.contour(bp.vertical(i / 10.0))
}
}
}
}
}

View File

@@ -15,44 +15,42 @@ import org.openrndr.shape.ShapeContour
* In this case the contours are regular stars and the bezier patch
* is created using a circular contour with the required 4 segments.
*/
fun main() {
application {
configure {
width = 800
height = 800
}
program {
val bp = bezierPatch(
Circle(width / 2.0, height / 2.0, 350.0).contour
)
val star = regularStarRounded(
7, 30.0, 40.0,
0.5, 0.5
)
fun main() = application {
configure {
width = 800
height = 800
}
program {
val bp = bezierPatch(
Circle(width / 2.0, height / 2.0, 350.0).contour
)
val star = regularStarRounded(
7, 30.0, 40.0,
0.5, 0.5
)
extend {
drawer.clear(ColorRGBa.PINK)
extend {
drawer.clear(ColorRGBa.PINK)
// draw grid
for (i in 0..50) {
drawer.stroke = ColorRGBa.BLACK
drawer.contour(bp.horizontal(i / 50.0))
drawer.contour(bp.vertical(i / 50.0))
}
// draw grid
for (i in 0..50) {
drawer.stroke = ColorRGBa.BLACK
drawer.contour(bp.horizontal(i / 50.0))
drawer.contour(bp.vertical(i / 50.0))
}
// draw stars
drawer.fill = ColorRGBa.PINK
for (j in 1 until 10) {
for (i in 1 until 10) {
val starMoved = star.transform(
transform {
translate(j * width / 10.0, i * height / 10.0)
}
)
drawer.contour(bp.distort(starMoved, drawer.bounds))
}
// draw stars
drawer.fill = ColorRGBa.PINK
for (j in 1 until 10) {
for (i in 1 until 10) {
val starMoved = star.transform(
transform {
translate(j * width / 10.0, i * height / 10.0)
}
)
drawer.contour(bp.distort(starMoved, drawer.bounds))
}
}
}
}
}
}

View File

@@ -12,35 +12,33 @@ import org.openrndr.shape.Circle
* You can think of bezierPatch.position() as requesting points
* in a wavy flag (the bezier patch) using normalized uv coordinates.
*/
fun main() {
application {
configure {
width = 800
height = 800
}
program {
val bp = bezierPatch(
Circle(drawer.bounds.center, 350.0).contour
//Rectangle.fromCenter(drawer.bounds.center, 550.0).contour
)
fun main() = application {
configure {
width = 800
height = 800
}
program {
val bp = bezierPatch(
Circle(drawer.bounds.center, 350.0).contour
//Rectangle.fromCenter(drawer.bounds.center, 550.0).contour
)
extend {
drawer.clear(ColorRGBa.PINK)
drawer.stroke = ColorRGBa.BLACK
extend {
drawer.clear(ColorRGBa.PINK)
drawer.stroke = ColorRGBa.BLACK
for (j in 1 until 50 step 2) {
for (i in 1 until 50 step 2) {
val u = i / 50.0
val v = j / 50.0
val pos = bp.position(u, v)
val grad = bp.gradient(u, v).normalized * 10.0
val perpendicular = grad.perpendicular()
drawer.lineSegment(pos - grad, pos + grad)
drawer.lineSegment(pos - perpendicular, pos + perpendicular)
//drawer.circle(pos + grad, 3.0)
}
for (j in 1 until 50 step 2) {
for (i in 1 until 50 step 2) {
val u = i / 50.0
val v = j / 50.0
val pos = bp.position(u, v)
val grad = bp.gradient(u, v).normalized * 10.0
val perpendicular = grad.perpendicular()
drawer.lineSegment(pos - grad, pos + grad)
drawer.lineSegment(pos - perpendicular, pos + perpendicular)
//drawer.circle(pos + grad, 3.0)
}
}
}
}
}
}

View File

@@ -3,8 +3,8 @@ package bezierpatch
import org.openrndr.WindowMultisample
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extra.shapes.bezierpatches.bezierPatch
import org.openrndr.extra.camera.Orbital
import org.openrndr.extra.shapes.bezierpatches.bezierPatch
import org.openrndr.math.Vector3
import org.openrndr.shape.Segment3D
@@ -19,56 +19,54 @@ import org.openrndr.shape.Segment3D
* The created contours are horizontal and vertical in "bezier-patch space" but
* are rendered deformed following the shape of the bezier patch.
*/
fun main() {
application {
configure {
width = 800
height = 800
multisample = WindowMultisample.SampleCount(8)
fun main() = application {
configure {
width = 800
height = 800
multisample = WindowMultisample.SampleCount(8)
}
program {
val c0 = Segment3D(Vector3(-5.0, 0.0, -9.0), Vector3(5.0, 0.0, -9.0))
val c1 = Segment3D(Vector3(-5.0, -5.0, -3.0), Vector3(5.0, -5.0, -3.0))
val c2 = Segment3D(Vector3(-5.0, 5.0, 3.0), Vector3(5.0, 5.0, 3.0))
val c3 = Segment3D(Vector3(-5.0, 0.0, 9.0), Vector3(5.0, 0.0, 9.0))
val col = listOf(ColorRGBa.PINK, ColorRGBa.RED, ColorRGBa.BLUE, ColorRGBa.PINK)
val cols = listOf(col, col, col, col)
val bp = bezierPatch(c0, c1, c2, c3).withColors(cols)
val bpSub = bp.sub(0.1, 0.1, 0.6, 0.6)
val cam = Orbital()
extend(cam) {
eye = Vector3(x = 9.9, y = 12.8, z = 6.9)
lookAt = Vector3(x = 1.6, y = -1.9, z = 1.2)
}
program {
val c0 = Segment3D(Vector3(-5.0, 0.0, -9.0), Vector3(5.0, 0.0, -9.0))
val c1 = Segment3D(Vector3(-5.0, -5.0, -3.0), Vector3(5.0, -5.0, -3.0))
val c2 = Segment3D(Vector3(-5.0, 5.0, 3.0), Vector3(5.0, 5.0, 3.0))
val c3 = Segment3D(Vector3(-5.0, 0.0, 9.0), Vector3(5.0, 0.0, 9.0))
val col = listOf(ColorRGBa.PINK, ColorRGBa.RED, ColorRGBa.BLUE, ColorRGBa.PINK)
val cols = listOf(col, col, col, col)
val bp = bezierPatch(c0, c1, c2, c3).withColors(cols)
val bpSub = bp.sub(0.1, 0.1, 0.6, 0.6)
extend {
drawer.clear(ColorRGBa.PINK)
val cam = Orbital()
extend(cam){
eye = Vector3(x=9.9, y=12.8, z=6.9)
lookAt = Vector3(x=1.6, y=-1.9, z=1.2)
drawer.translate(-5.0, 0.0, 0.0)
// Show the segments that form the bezier patch
drawer.stroke = ColorRGBa.YELLOW
drawer.strokeWeight = 50.0
drawer.segments(listOf(c0, c1, c2, c3))
// Show the grid
drawer.strokeWeight = 1.0
val n = 10
for (i in 0..n) {
drawer.stroke = ColorRGBa.BLACK
drawer.lineStrip(bp.horizontal(i / n.toDouble()).adaptivePositions(0.01))
drawer.lineStrip(bp.vertical(i / n.toDouble()).adaptivePositions(0.01))
drawer.stroke = ColorRGBa.RED
drawer.lineStrip(bpSub.horizontal(i / n.toDouble()).adaptivePositions(0.01))
drawer.lineStrip(bpSub.vertical(i / n.toDouble()).adaptivePositions(0.01))
}
extend {
drawer.clear(ColorRGBa.PINK)
drawer.translate(-5.0, 0.0, 0.0)
// Show the segments that form the bezier patch
drawer.stroke = ColorRGBa.YELLOW
drawer.strokeWeight = 50.0
drawer.segments(listOf(c0, c1, c2, c3))
// Show the grid
drawer.strokeWeight = 1.0
val n = 10
for (i in 0..n) {
drawer.stroke = ColorRGBa.BLACK
drawer.lineStrip(bp.horizontal(i / n.toDouble()).adaptivePositions(0.01))
drawer.lineStrip(bp.vertical(i / n.toDouble()).adaptivePositions(0.01))
drawer.stroke = ColorRGBa.RED
drawer.lineStrip(bpSub.horizontal(i / n.toDouble()).adaptivePositions(0.01))
drawer.lineStrip(bpSub.vertical(i / n.toDouble()).adaptivePositions(0.01))
}
// Draw the colored Bezier surface
drawer.translate(10.0, 0.0, 0.0)
drawer.bezierPatch(bp)
}
// Draw the colored Bezier surface
drawer.translate(10.0, 0.0, 0.0)
drawer.bezierPatch(bp)
}
}
}
}

View File

@@ -5,33 +5,31 @@ import org.openrndr.color.ColorRGBa
import org.openrndr.extra.shapes.bezierpatches.bezierPatch
import org.openrndr.shape.Circle
fun main() {
application {
program {
extend {
drawer.clear(ColorRGBa.PINK)
val bp = bezierPatch(
Circle(width/2.0, height/2.0, 200.0).contour
).withColors(
listOf(
fun main() = application {
program {
extend {
drawer.clear(ColorRGBa.PINK)
val bp = bezierPatch(
Circle(width / 2.0, height / 2.0, 200.0).contour
).withColors(
listOf(
listOf(ColorRGBa.PINK, ColorRGBa.RED, ColorRGBa.BLACK, ColorRGBa.BLUE),
listOf(ColorRGBa.RED, ColorRGBa.BLACK, ColorRGBa.BLUE, ColorRGBa.GREEN),
listOf(ColorRGBa.PINK, ColorRGBa.RED, ColorRGBa.WHITE, ColorRGBa.GREEN),
listOf(ColorRGBa.BLACK, ColorRGBa.WHITE, ColorRGBa.BLACK, ColorRGBa.BLUE),
)
listOf(ColorRGBa.RED, ColorRGBa.BLACK, ColorRGBa.BLUE, ColorRGBa.GREEN),
listOf(ColorRGBa.PINK, ColorRGBa.RED, ColorRGBa.WHITE, ColorRGBa.GREEN),
listOf(ColorRGBa.BLACK, ColorRGBa.WHITE, ColorRGBa.BLACK, ColorRGBa.BLUE),
)
)
drawer.bezierPatch(bp)
drawer.bezierPatch(bp)
drawer.fill = null
drawer.contour(bp.contour)
for (i in 0 until 10) {
drawer.contour(bp.horizontal(i/9.0))
}
for (i in 0 until 10) {
drawer.contour(bp.vertical(i/9.0))
}
drawer.fill = null
drawer.contour(bp.contour)
for (i in 0 until 10) {
drawer.contour(bp.horizontal(i / 9.0))
}
for (i in 0 until 10) {
drawer.contour(bp.vertical(i / 9.0))
}
}
}
}
}

View File

@@ -7,43 +7,61 @@ import org.openrndr.extra.color.spaces.toOKLABa
import org.openrndr.extra.shapes.bezierpatches.bezierPatch
import org.openrndr.shape.Circle
fun main() {
application {
configure {
width = 720
height = 720
}
program {
extend {
drawer.clear(ColorRGBa.BLACK)
val bp2 = bezierPatch(
Circle(width/2.0 - 180.0, height/2.0, 170.0).contour
).withColors(
listOf(
fun main() = application {
configure {
width = 720
height = 720
}
program {
extend {
drawer.clear(ColorRGBa.BLACK)
val bp2 = bezierPatch(
Circle(width / 2.0 - 180.0, height / 2.0, 170.0).contour
).withColors(
listOf(
listOf(ColorRGBa.PINK, ColorRGBa.PINK, ColorRGBa.PINK, ColorRGBa.PINK),
listOf(ColorRGBa.RED, ColorRGBa.RED, ColorRGBa.RED, ColorRGBa.RED),
listOf(ColorRGBa.BLUE, ColorRGBa.BLUE, ColorRGBa.BLUE, ColorRGBa.BLUE),
listOf(ColorRGBa.WHITE, ColorRGBa.WHITE, ColorRGBa.WHITE, ColorRGBa.WHITE),
)
listOf(ColorRGBa.RED, ColorRGBa.RED, ColorRGBa.RED, ColorRGBa.RED),
listOf(ColorRGBa.BLUE, ColorRGBa.BLUE, ColorRGBa.BLUE, ColorRGBa.BLUE),
listOf(ColorRGBa.WHITE, ColorRGBa.WHITE, ColorRGBa.WHITE, ColorRGBa.WHITE),
)
drawer.bezierPatch(bp2)
val bp3 = bezierPatch(
Circle(width/2.0 + 180.0, height/2.0, 170.0).contour
).withColors(
)
drawer.bezierPatch(bp2)
val bp3 = bezierPatch(
Circle(width / 2.0 + 180.0, height / 2.0, 170.0).contour
).withColors(
listOf(
listOf(
listOf(ColorRGBa.PINK.toOKLABa(), ColorRGBa.PINK.toOKLABa(), ColorRGBa.PINK.toOKLABa(), ColorRGBa.PINK.toOKLABa()),
listOf(ColorRGBa.RED.toOKLABa(), ColorRGBa.RED.toOKLABa(), ColorRGBa.RED.toOKLABa(), ColorRGBa.RED.toOKLABa()),
listOf(ColorRGBa.BLUE.toOKLABa(), ColorRGBa.BLUE.toOKLABa(), ColorRGBa.BLUE.toOKLABa(), ColorRGBa.BLUE.toOKLABa()),
listOf(ColorRGBa.WHITE.toOKLABa(), ColorRGBa.WHITE.toOKLABa(), ColorRGBa.WHITE.toOKLABa(), ColorRGBa.WHITE.toOKLABa()),
)
ColorRGBa.PINK.toOKLABa(),
ColorRGBa.PINK.toOKLABa(),
ColorRGBa.PINK.toOKLABa(),
ColorRGBa.PINK.toOKLABa()
),
listOf(
ColorRGBa.RED.toOKLABa(),
ColorRGBa.RED.toOKLABa(),
ColorRGBa.RED.toOKLABa(),
ColorRGBa.RED.toOKLABa()
),
listOf(
ColorRGBa.BLUE.toOKLABa(),
ColorRGBa.BLUE.toOKLABa(),
ColorRGBa.BLUE.toOKLABa(),
ColorRGBa.BLUE.toOKLABa()
),
listOf(
ColorRGBa.WHITE.toOKLABa(),
ColorRGBa.WHITE.toOKLABa(),
ColorRGBa.WHITE.toOKLABa(),
ColorRGBa.WHITE.toOKLABa()
),
)
drawer.bezierPatch(bp3)
)
drawer.bezierPatch(bp3)
drawer.fill = ColorRGBa.WHITE
drawer.fontMap = loadFont("demo-data/fonts/IBMPlexMono-Regular.ttf", 16.0)
drawer.text("RGB", width/2.0 - 180.0, height/2.0 + 200.0)
drawer.text("OKLab", width/2.0 + 180.0, height/2.0 + 200.0)
}
drawer.fill = ColorRGBa.WHITE
drawer.fontMap = loadFont("demo-data/fonts/IBMPlexMono-Regular.ttf", 16.0)
drawer.text("RGB", width / 2.0 - 180.0, height / 2.0 + 200.0)
drawer.text("OKLab", width / 2.0 + 180.0, height / 2.0 + 200.0)
}
}
}
}

View File

@@ -13,49 +13,67 @@ import org.openrndr.shape.Circle
import org.openrndr.shape.Rectangle
import kotlin.math.min
fun main() {
application {
configure {
width = 720
height = 720
}
program {
extend {
drawer.clear(ColorRGBa.BLACK)
val colors = listOf(
listOf(ColorRGBa.PINK.toOKLABa(), ColorRGBa.PINK.toOKLABa(), ColorRGBa.PINK.toOKLABa(), ColorRGBa.PINK.toOKLABa()),
listOf(ColorRGBa.RED.toOKLABa(), ColorRGBa.RED.toOKLABa(), ColorRGBa.RED.toOKLABa(), ColorRGBa.RED.toOKLABa()),
listOf(ColorRGBa.BLUE.toOKLABa(), ColorRGBa.BLUE.toOKLABa(), ColorRGBa.BLUE.toOKLABa(), ColorRGBa.BLUE.toOKLABa()),
listOf(ColorRGBa.WHITE.toOKLABa(), ColorRGBa.WHITE.toOKLABa(), ColorRGBa.WHITE.toOKLABa(), ColorRGBa.WHITE.toOKLABa()),
fun main() = application {
configure {
width = 720
height = 720
}
program {
extend {
drawer.clear(ColorRGBa.BLACK)
val colors = listOf(
listOf(
ColorRGBa.PINK.toOKLABa(),
ColorRGBa.PINK.toOKLABa(),
ColorRGBa.PINK.toOKLABa(),
ColorRGBa.PINK.toOKLABa()
),
listOf(
ColorRGBa.RED.toOKLABa(),
ColorRGBa.RED.toOKLABa(),
ColorRGBa.RED.toOKLABa(),
ColorRGBa.RED.toOKLABa()
),
listOf(
ColorRGBa.BLUE.toOKLABa(),
ColorRGBa.BLUE.toOKLABa(),
ColorRGBa.BLUE.toOKLABa(),
ColorRGBa.BLUE.toOKLABa()
),
listOf(
ColorRGBa.WHITE.toOKLABa(),
ColorRGBa.WHITE.toOKLABa(),
ColorRGBa.WHITE.toOKLABa(),
ColorRGBa.WHITE.toOKLABa()
),
)
val grid = drawer.bounds.grid(4, 4, marginX = 20.0, marginY = 20.0, gutterX = 10.0, gutterY = 10.0)
val cellWidth = grid[0][0].width
val cellHeight = grid[0][0].height
val a = bezierPatch(Rectangle.fromCenter(Vector2(0.0, 0.0), cellWidth, cellHeight).contour)
.withColors(colors)
val b = bezierPatch(
Circle(0.0, 0.0, min(cellWidth, cellHeight) / 2.0).contour.transform(
buildTransform {
rotate(Vector3.UNIT_Z, 45.0)
}
)
).withColors(colors)
val grid = drawer.bounds.grid(4,4, marginX = 20.0, marginY = 20.0, gutterX = 10.0, gutterY = 10.0)
val cellWidth = grid[0][0].width
val cellHeight = grid[0][0].height
val a = bezierPatch(Rectangle.fromCenter(Vector2(0.0, 0.0), cellWidth, cellHeight).contour)
.withColors(colors)
val b = bezierPatch(
Circle(0.0, 0.0, min(cellWidth, cellHeight) / 2.0).contour.transform(
buildTransform {
rotate(Vector3.UNIT_Z, 45.0)
}
)
).withColors(colors)
for (y in grid.indices) {
for (x in grid[y].indices) {
val f = (y * grid[y].size + x).toDouble() / (grid.size * grid[y].size - 1.0)
val blend = a * (1.0 - f) + b * f
drawer.isolated {
drawer.translate(grid[y][x].center)
drawer.bezierPatch(blend)
}
for (y in grid.indices) {
for (x in grid[y].indices) {
val f = (y * grid[y].size + x).toDouble() / (grid.size * grid[y].size - 1.0)
val blend = a * (1.0 - f) + b * f
drawer.isolated {
drawer.translate(grid[y][x].center)
drawer.bezierPatch(blend)
}
}
}
}
}
}
}

View File

@@ -15,23 +15,21 @@ import org.openrndr.shape.ShapeContour
* but one can manually create any other 4-segment closed contour
* to use in bezier patches.
*/
fun main() {
application {
configure {
width = 800
height = 800
}
program {
val c0 = Circle(width / 3.0, height / 2.0, 150.0).contour
val bp0 = bezierPatch(c0)
fun main() = application {
configure {
width = 800
height = 800
}
program {
val c0 = Circle(width / 3.0, height / 2.0, 150.0).contour
val bp0 = bezierPatch(c0)
val c1 = Circle(2.0*width / 3.0, height / 2.0, 150.0).contour
val bp1 = bezierPatch(c1)
val c1 = Circle(2.0 * width / 3.0, height / 2.0, 150.0).contour
val bp1 = bezierPatch(c1)
extend {
drawer.bezierPatches(listOf(bp0, bp1))
}
extend {
drawer.bezierPatches(listOf(bp0, bp1))
}
}
}
}

View File

@@ -10,28 +10,25 @@ import org.openrndr.shape.Circle
import kotlin.math.PI
import kotlin.math.cos
/**
* Demonstration of uniform contour blending
*/
fun main() {
application {
configure {
width = 720
height = 720
}
program {
val a = Circle(Vector2.ZERO, 90.0).contour
val b = regularStar(5, 30.0, 90.0, center = Vector2.ZERO, phase = 180.0)
val blend = a.blend(b)
extend {
drawer.bounds.grid(3, 3).flatten().forEachIndexed { index, it ->
drawer.isolated {
drawer.translate(it.center)
drawer.contour(blend.mix(cos(index * PI * 2.0 / 9.0 + seconds) * 0.5 + 0.5))
}
fun main() = application {
configure {
width = 720
height = 720
}
program {
val a = Circle(Vector2.ZERO, 90.0).contour
val b = regularStar(5, 30.0, 90.0, center = Vector2.ZERO, phase = 180.0)
val blend = a.blend(b)
extend {
drawer.bounds.grid(3, 3).flatten().forEachIndexed { index, it ->
drawer.isolated {
drawer.translate(it.center)
drawer.contour(blend.mix(cos(index * PI * 2.0 / 9.0 + seconds) * 0.5 + 0.5))
}
}
}
}
}
}

View File

@@ -14,26 +14,24 @@ import kotlin.math.cos
/**
* Demonstration of non-uniform contour blending
*/
fun main() {
application {
configure {
width = 720
height = 720
}
program {
val a = Circle(Vector2.ZERO, 90.0).contour
val b = regularStar(5, 30.0, 90.0, center = Vector2.ZERO, phase = 180.0)
val blend = a.blend(b)
extend {
drawer.clear(ColorRGBa.WHITE)
drawer.fill = ColorRGBa.BLACK
drawer.bounds.grid(3, 3).flatten().forEachIndexed { index, it ->
drawer.isolated {
drawer.translate(it.center)
drawer.contour(blend.mix { t -> cos(t * PI * 2.0 + index * PI * 2.0 / 9.0 + seconds) * 0.5 + 0.5 })
}
fun main() = application {
configure {
width = 720
height = 720
}
program {
val a = Circle(Vector2.ZERO, 90.0).contour
val b = regularStar(5, 30.0, 90.0, center = Vector2.ZERO, phase = 180.0)
val blend = a.blend(b)
extend {
drawer.clear(ColorRGBa.WHITE)
drawer.fill = ColorRGBa.BLACK
drawer.bounds.grid(3, 3).flatten().forEachIndexed { index, it ->
drawer.isolated {
drawer.translate(it.center)
drawer.contour(blend.mix { t -> cos(t * PI * 2.0 + index * PI * 2.0 / 9.0 + seconds) * 0.5 + 0.5 })
}
}
}
}
}
}

View File

@@ -15,53 +15,50 @@ import org.openrndr.math.Vector3
import org.openrndr.shape.path3D
import kotlin.random.Random
fun main() {
application {
configure {
width = 720
height = 720
multisample = WindowMultisample.SampleCount(4)
}
program {
val random = Random(0)
val cylinder = cylinderMesh(radius = 0.5, length = 0.1)
val p = path3D {
moveTo(0.0, 0.0, 0.0)
curveTo(
Vector3.uniformRing(0.1, 1.0, random = random)*10.0,
Vector3.uniformRing(0.1, 1.0, random = random)*10.0,
Vector3.uniformRing(0.1, 1.0, random = random)*10.0
fun main() = application {
configure {
width = 720
height = 720
multisample = WindowMultisample.SampleCount(4)
}
program {
val random = Random(0)
val cylinder = cylinderMesh(radius = 0.5, length = 0.1)
val p = path3D {
moveTo(0.0, 0.0, 0.0)
curveTo(
Vector3.uniformRing(0.1, 1.0, random = random) * 10.0,
Vector3.uniformRing(0.1, 1.0, random = random) * 10.0,
Vector3.uniformRing(0.1, 1.0, random = random) * 10.0
)
for (i in 0 until 10) {
continueTo(
Vector3.uniformRing(0.1, 1.0, random = random) * 10.0,
Vector3.uniformRing(0.1, 1.0, random = random) * 10.0
)
for (i in 0 until 10) {
continueTo(
Vector3.uniformRing(0.1, 1.0, random = random)*10.0,
Vector3.uniformRing(0.1, 1.0, random = random)*10.0
)
}
}
val pr = p.rectified(0.01, 100.0)
}
val pr = p.rectified(0.01, 100.0)
val frames = pr.frames((0 until 100).map { it / 100.0}, Vector3.UNIT_Y, analyticalDirections = false)
extend(Orbital())
extend {
drawer.shadeStyle = shadeStyle {
fragmentTransform = """
val frames = pr.frames((0 until 100).map { it / 100.0 }, Vector3.UNIT_Y, analyticalDirections = false)
extend(Orbital())
extend {
drawer.shadeStyle = shadeStyle {
fragmentTransform = """
x_fill.rgb = vec3(abs(v_viewNormal.z)*0.9+ 0.1);
""".trimIndent()
}
drawer.stroke = ColorRGBa.PINK
drawer.path(p)
for (frame in frames) {
drawer.isolated {
drawer.model = frame
drawer.vertexBuffer(cylinder, DrawPrimitive.TRIANGLES)
}
drawer.stroke = ColorRGBa.PINK
drawer.path(p)
for (frame in frames) {
drawer.isolated {
drawer.model = frame
drawer.vertexBuffer(cylinder, DrawPrimitive.TRIANGLES)
}
}
}
}
}
}
}

View File

@@ -6,20 +6,18 @@ import org.openrndr.extra.noise.uniform
import org.openrndr.extra.shapes.ordering.hilbertOrder
import kotlin.random.Random
fun main() {
application {
configure {
width = 720
height = 720
}
program {
val points = drawer.bounds.offsetEdges(-20.0).uniform(40, Random(0))
val sortedPoints = points.hilbertOrder(bits = 16, scale = 1.0)
extend {
drawer.clear(ColorRGBa.PINK)
drawer.stroke = ColorRGBa.RED
drawer.lineStrip(sortedPoints)
}
fun main() = application {
configure {
width = 720
height = 720
}
program {
val points = drawer.bounds.offsetEdges(-20.0).uniform(40, Random(0))
val sortedPoints = points.hilbertOrder(bits = 16, scale = 1.0)
extend {
drawer.clear(ColorRGBa.PINK)
drawer.stroke = ColorRGBa.RED
drawer.lineStrip(sortedPoints)
}
}
}
}

View File

@@ -4,26 +4,23 @@ import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extra.noise.uniform
import org.openrndr.extra.shapes.ordering.hilbertOrder
import org.openrndr.extra.shapes.ordering.mortonOrder
import kotlin.random.Random
fun main() {
application {
configure {
width = 720
height = 720
}
program {
val points = drawer.bounds.offsetEdges(-20.0).uniform(400, Random(0))
val sortedPoints0 = points.hilbertOrder(bits = 16, scale = 1.0)
val sortedPoints1 = points.map { it.xy0 }.hilbertOrder(bits = 10, scale = 1.0).map { it.xy }
extend {
drawer.clear(ColorRGBa.PINK)
drawer.stroke = ColorRGBa.RED
drawer.lineStrip(sortedPoints0)
drawer.stroke = ColorRGBa.BLUE
drawer.lineStrip(sortedPoints1)
}
fun main() = application {
configure {
width = 720
height = 720
}
program {
val points = drawer.bounds.offsetEdges(-20.0).uniform(400, Random(0))
val sortedPoints0 = points.hilbertOrder(bits = 16, scale = 1.0)
val sortedPoints1 = points.map { it.xy0 }.hilbertOrder(bits = 10, scale = 1.0).map { it.xy }
extend {
drawer.clear(ColorRGBa.PINK)
drawer.stroke = ColorRGBa.RED
drawer.lineStrip(sortedPoints0)
drawer.stroke = ColorRGBa.BLUE
drawer.lineStrip(sortedPoints1)
}
}
}
}

View File

@@ -4,38 +4,31 @@ import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.draw.LineJoin
import org.openrndr.extra.camera.Orbital
import org.openrndr.extra.noise.uniformRing
import org.openrndr.extra.shapes.path3d.projectToContour
import org.openrndr.math.Spherical
import org.openrndr.math.Vector3
import org.openrndr.shape.path3D
fun main() {
application {
configure {
width = 720
height = 720
fun main() = application {
program {
val path = path3D {
var p = Vector3(6.0, 0.0, 0.0)
moveTo(p)
for (i in 0 until 100) {
p = Spherical((i % 6) * 45.0, (i % 4 + 1) * 30.0 + i * 0.1, 6.0).cartesian
arcTo(5.0, cursor.atan2(p), false, false, p)
}
}
program {
val path = path3D {
var p = Vector3(1.0, 0.0, 0.0)
moveTo(p * 6.0)
for (i in 0 until 400) {
p += Vector3.uniformRing(0.2, 0.5)
p = p.normalized
arcTo(5.0, cursor.atan2(p * 6.0), false, false, p * 6.0)
}
}
extend(Orbital())
extend {
drawer.stroke = ColorRGBa.PINK
drawer.path(path)
val c = path.projectToContour(drawer.projection, drawer.view, width, height)
drawer.defaults()
drawer.stroke = ColorRGBa.WHITE
drawer.lineJoin = LineJoin.ROUND
drawer.strokeWeight = 2.0
drawer.contour(c)
}
extend(Orbital())
extend {
drawer.stroke = ColorRGBa.PINK
drawer.path(path)
val c = path.projectToContour(drawer.projection, drawer.view, width, height)
drawer.defaults()
drawer.stroke = ColorRGBa.WHITE
drawer.lineJoin = LineJoin.ROUND
drawer.strokeWeight = 2.0
drawer.contour(c)
}
}
}
}

View File

@@ -4,21 +4,19 @@ import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extra.shapes.primitives.Arc
fun main() {
application {
configure {
width = 720
height = 720
}
program {
extend {
val a = Arc(drawer.bounds.center, 100.0, 0.0 + seconds * 36.0, -180.0 + seconds * 36.0)
drawer.clear(ColorRGBa.PINK)
drawer.contour(a.contour)
drawer.circle(a.position(0.0), 5.0)
drawer.circle(a.position(0.5), 5.0)
drawer.circle(a.position(1.0), 5.0)
}
fun main() = application {
configure {
width = 720
height = 720
}
program {
extend {
val a = Arc(drawer.bounds.center, 100.0, 0.0 + seconds * 36.0, -180.0 + seconds * 36.0)
drawer.clear(ColorRGBa.PINK)
drawer.contour(a.contour)
drawer.circle(a.position(0.0), 5.0)
drawer.circle(a.position(0.5), 5.0)
drawer.circle(a.position(1.0), 5.0)
}
}
}
}

View File

@@ -6,29 +6,27 @@ import org.openrndr.extra.shapes.primitives.Net
import org.openrndr.shape.Circle
import kotlin.math.sin
fun main() {
application {
program {
extend {
drawer.clear(ColorRGBa.BLACK)
drawer.stroke = ColorRGBa.WHITE
drawer.fill = ColorRGBa.PINK
val a = drawer.bounds.position(0.7, 0.5)
val b = drawer.bounds.position(0.3, 0.5)
val c = Circle(
drawer.bounds.position(
sin(seconds) * 0.35 + 0.5,
sin(seconds * 2) * 0.25 + 0.5
), 50.0
)
val net = Net(a, b, c)
drawer.circle(a, 10.0)
drawer.circle(b, 10.0)
drawer.circle(c)
fun main() = application {
program {
extend {
drawer.clear(ColorRGBa.BLACK)
drawer.stroke = ColorRGBa.WHITE
drawer.fill = ColorRGBa.PINK
val a = drawer.bounds.position(0.7, 0.5)
val b = drawer.bounds.position(0.3, 0.5)
val c = Circle(
drawer.bounds.position(
sin(seconds) * 0.35 + 0.5,
sin(seconds * 2) * 0.25 + 0.5
), 50.0
)
val net = Net(a, b, c)
drawer.circle(a, 10.0)
drawer.circle(b, 10.0)
drawer.circle(c)
drawer.strokeWeight = 2.0
drawer.contour(net.contour)
}
drawer.strokeWeight = 2.0
drawer.contour(net.contour)
}
}
}
}

View File

@@ -6,23 +6,21 @@ import org.openrndr.extra.shapes.primitives.Pulley
import org.openrndr.math.Vector2
import org.openrndr.shape.Circle
fun main() {
application {
configure {
width = 720
height = 720
}
program {
extend {
drawer.clear(ColorRGBa.BLACK)
drawer.stroke = ColorRGBa.WHITE
drawer.fill = ColorRGBa.PINK
val pulley = Pulley(
Circle(drawer.bounds.center - Vector2(100.0, 100.0), 150.0),
Circle(drawer.bounds.center + Vector2(150.0, 150.0), 75.0)
)
drawer.contour(pulley.contour)
}
fun main() = application {
configure {
width = 720
height = 720
}
program {
extend {
drawer.clear(ColorRGBa.BLACK)
drawer.stroke = ColorRGBa.WHITE
drawer.fill = ColorRGBa.PINK
val pulley = Pulley(
Circle(drawer.bounds.center - Vector2(100.0, 100.0), 150.0),
Circle(drawer.bounds.center + Vector2(150.0, 150.0), 75.0)
)
drawer.contour(pulley.contour)
}
}
}
}

View File

@@ -4,25 +4,23 @@ import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extra.shapes.primitives.grid
fun main() {
application {
configure {
width = 800
height = 800
}
program {
extend {
drawer.fill = ColorRGBa.WHITE.opacify(0.25)
drawer.stroke = ColorRGBa.PINK
fun main() = application {
configure {
width = 800
height = 800
}
program {
extend {
drawer.fill = ColorRGBa.WHITE.opacify(0.25)
drawer.stroke = ColorRGBa.PINK
// Notice the negative gutter in this grid. It creates an
// overlap between the resulting rectangles.
val grid = drawer.bounds.grid(8, 4, 20.0, 20.0, -20.0, -20.0)
for (cell in grid.flatten()) {
drawer.rectangle(cell)
drawer.lineSegment(cell.position(0.0, 0.0), cell.position(1.0, 1.0))
}
// Notice the negative gutter in this grid. It creates an
// overlap between the resulting rectangles.
val grid = drawer.bounds.grid(8, 4, 20.0, 20.0, -20.0, -20.0)
for (cell in grid.flatten()) {
drawer.rectangle(cell)
drawer.lineSegment(cell.position(0.0, 0.0), cell.position(1.0, 1.0))
}
}
}
}
}

View File

@@ -5,35 +5,35 @@ import org.openrndr.color.ColorRGBa
import org.openrndr.extra.noise.Random
import org.openrndr.extra.shapes.primitives.grid
fun main() {
application {
// Try changing the resolution. The design will use the available space.
configure {
width = 800
height = 400
}
program {
// By specifying the cell size we make sure the design will
// contain squares, independently of the window size and its
// aspect ratio.
val grid = drawer.bounds.grid(50.0, 50.0,
20.0, 20.0, 20.0, 20.0).flatten()
fun main() = application {
// Try changing the resolution. The design will use the available space.
configure {
width = 800
height = 400
}
program {
// By specifying the cell size we make sure the design will
// contain squares, independently of the window size and its
// aspect ratio.
val grid = drawer.bounds.grid(
50.0, 50.0,
20.0, 20.0, 20.0, 20.0
).flatten()
val grid2 = grid.map { rect ->
// Each of these inner grids will occupy the available space
// in the parent grid cells. Notice how we don't specify cell
// sizes here but counts instead (between 1 and 3 columns and
// rows)
val count = Random.int(1, 4)
rect.grid(count, count, 5.0, 5.0, 5.0, 5.0).flatten()
}.flatten().filter { Random.bool(0.5)}
val grid2 = grid.map { rect ->
// Each of these inner grids will occupy the available space
// in the parent grid cells. Notice how we don't specify cell
// sizes here but counts instead (between 1 and 3 columns and
// rows)
val count = Random.int(1, 4)
rect.grid(count, count, 5.0, 5.0, 5.0, 5.0).flatten()
}.flatten().filter { Random.bool(0.5) }
extend {
drawer.clear(ColorRGBa.PINK)
drawer.rectangles(grid)
drawer.fill = ColorRGBa.BLACK
drawer.rectangles(grid2)
}
extend {
drawer.clear(ColorRGBa.PINK)
drawer.rectangles(grid)
drawer.fill = ColorRGBa.BLACK
drawer.rectangles(grid2)
}
}
}
}

View File

@@ -8,33 +8,31 @@ import org.openrndr.extra.shapes.primitives.intersection
* Demonstrate rectangle-rectangle intersection
* @see <img src="https://raw.githubusercontent.com/openrndr/orx/media/orx-shapes/images/primitives-DemoRectangleIntersection01Kt.png">
*/
fun main() {
application {
configure {
width = 720
height = 720
}
program {
val h = drawer.bounds.offsetEdges(-100.0, -10.0)
val v = drawer.bounds.offsetEdges(-10.0, -100.0)
fun main() = application {
configure {
width = 720
height = 720
}
program {
val h = drawer.bounds.offsetEdges(-100.0, -10.0)
val v = drawer.bounds.offsetEdges(-10.0, -100.0)
extend {
drawer.clear(ColorRGBa.WHITE)
extend {
drawer.clear(ColorRGBa.WHITE)
/**
* Find intersection
*/
val i = h.intersection(v)
drawer.fill = ColorRGBa.RED
drawer.rectangle(h)
/**
* Find intersection
*/
val i = h.intersection(v)
drawer.fill = ColorRGBa.RED
drawer.rectangle(h)
drawer.fill = ColorRGBa.BLUE
drawer.rectangle(v)
drawer.fill = ColorRGBa.BLUE
drawer.rectangle(v)
drawer.fill = ColorRGBa.BLACK
drawer.stroke = ColorRGBa.WHITE
drawer.rectangle(i)
}
drawer.fill = ColorRGBa.BLACK
drawer.stroke = ColorRGBa.WHITE
drawer.rectangle(i)
}
}
}
}

View File

@@ -8,24 +8,22 @@ import org.openrndr.math.Vector2
import org.openrndr.shape.Circle
import kotlin.random.Random
fun main() {
application {
configure {
width = 720
height = 720
fun main() = application {
configure {
width = 720
height = 720
}
program {
val points = drawer.bounds.scatter(40.0, distanceToEdge = 150.0, random = Random(0))
val tears = points.map {
Tear(it - Vector2(0.0, 20.0), Circle(it + Vector2(0.0, 20.0), 20.0))
}
program {
val points = drawer.bounds.scatter(40.0, distanceToEdge = 150.0, random = Random(0))
val tears = points.map {
Tear(it - Vector2(0.0, 20.0), Circle(it + Vector2(0.0, 20.0), 20.0))
}
extend {
drawer.clear(ColorRGBa.BLACK)
drawer.fill = ColorRGBa.PINK
drawer.stroke = ColorRGBa.WHITE
drawer.contours(tears.map { it.contour })
}
extend {
drawer.clear(ColorRGBa.BLACK)
drawer.fill = ColorRGBa.PINK
drawer.stroke = ColorRGBa.WHITE
drawer.contours(tears.map { it.contour })
}
}
}
}

View File

@@ -7,26 +7,24 @@ import org.openrndr.extra.shapes.hobbycurve.hobbyCurve
import org.openrndr.extra.shapes.rectify.rectified
import kotlin.random.Random
fun main() {
application {
configure {
width = 720
height = 720
}
program {
val points = drawer.bounds.scatter(50.0, distanceToEdge = 100.0, random = Random(0))
val curve = hobbyCurve(points)
val rectified = curve.rectified()
extend {
drawer.clear(ColorRGBa.BLACK)
drawer.stroke = ColorRGBa.PINK
drawer.contour(curve)
drawer.fill = ColorRGBa.RED
drawer.circle(curve.position(seconds*0.05), 10.0)
drawer.fill = ColorRGBa.GREEN
drawer.circle(rectified.position(seconds*0.05), 10.0)
fun main() = application {
configure {
width = 720
height = 720
}
program {
val points = drawer.bounds.scatter(50.0, distanceToEdge = 100.0, random = Random(0))
val curve = hobbyCurve(points)
val rectified = curve.rectified()
extend {
drawer.clear(ColorRGBa.BLACK)
drawer.stroke = ColorRGBa.PINK
drawer.contour(curve)
drawer.fill = ColorRGBa.RED
drawer.circle(curve.position(seconds * 0.05), 10.0)
drawer.fill = ColorRGBa.GREEN
drawer.circle(rectified.position(seconds * 0.05), 10.0)
}
}
}
}
}

View File

@@ -7,29 +7,27 @@ import org.openrndr.extra.shapes.hobbycurve.hobbyCurve
import org.openrndr.extra.shapes.rectify.rectified
import kotlin.random.Random
fun main() {
application {
configure {
width = 720
height = 720
}
program {
val points = drawer.bounds.scatter(80.0, distanceToEdge = 100.0, random = Random(0))
val curve = hobbyCurve(points, closed = true)
val rectified = curve.rectified()
extend {
drawer.clear(ColorRGBa.BLACK)
drawer.fill = null
drawer.stroke = ColorRGBa.GRAY
drawer.contour(curve)
drawer.strokeWeight = 4.0
fun main() = application {
configure {
width = 720
height = 720
}
program {
val points = drawer.bounds.scatter(80.0, distanceToEdge = 100.0, random = Random(0))
val curve = hobbyCurve(points, closed = true)
val rectified = curve.rectified()
extend {
drawer.clear(ColorRGBa.BLACK)
drawer.fill = null
drawer.stroke = ColorRGBa.GRAY
drawer.contour(curve)
drawer.strokeWeight = 4.0
drawer.stroke = ColorRGBa.RED
drawer.contour(curve.sub(seconds*0.1, seconds*0.1+0.01))
drawer.stroke = ColorRGBa.RED
drawer.contour(curve.sub(seconds * 0.1, seconds * 0.1 + 0.01))
drawer.stroke = ColorRGBa.GREEN
drawer.contour(rectified.sub(seconds*0.1, seconds*0.1+0.01))
}
drawer.stroke = ColorRGBa.GREEN
drawer.contour(rectified.sub(seconds * 0.1, seconds * 0.1 + 0.01))
}
}
}
}

View File

@@ -7,28 +7,26 @@ import org.openrndr.extra.shapes.hobbycurve.hobbyCurve
import org.openrndr.extra.shapes.rectify.rectified
import kotlin.random.Random
fun main() {
application {
configure {
width = 720
height = 720
}
program {
val points = drawer.bounds.scatter(80.0, distanceToEdge = 100.0, random = Random(0))
val curve = hobbyCurve(points, closed = true)
val rectified = curve.rectified()
extend {
drawer.clear(ColorRGBa.BLACK)
drawer.fill = null
drawer.stroke = ColorRGBa.GRAY
drawer.contour(curve)
val points = (0 until 100).map {
rectified.position(it/100.0)
}
drawer.circles(points, 5.0)
fun main() = application {
configure {
width = 720
height = 720
}
program {
val points = drawer.bounds.scatter(80.0, distanceToEdge = 100.0, random = Random(0))
val curve = hobbyCurve(points, closed = true)
val rectified = curve.rectified()
extend {
drawer.clear(ColorRGBa.BLACK)
drawer.fill = null
drawer.stroke = ColorRGBa.GRAY
drawer.contour(curve)
val points = (0 until 100).map {
rectified.position(it / 100.0)
}
drawer.circles(points, 5.0)
}
}
}
}

View File

@@ -12,38 +12,35 @@ import org.openrndr.extra.shapes.rectify.rectified
import org.openrndr.math.Vector3
import org.openrndr.shape.path3D
fun main() {
application {
configure {
width = 720
height = 720
multisample = WindowMultisample.SampleCount(4)
fun main() = application {
configure {
width = 720
height = 720
multisample = WindowMultisample.SampleCount(4)
}
program {
val p = path3D {
moveTo(0.0, 0.0, 0.0)
for (i in 0 until 10) {
curveTo(
Vector3.uniformRing(0.1, 1.0) * 10.0,
Vector3.uniformRing(0.1, 1.0) * 10.0,
Vector3.uniformRing(0.1, 1.0) * 10.0
)
}
}
program {
val p = path3D {
moveTo(0.0, 0.0, 0.0)
for (i in 0 until 10) {
curveTo(
Vector3.uniformRing(0.1, 1.0)*10.0,
Vector3.uniformRing(0.1, 1.0)*10.0,
Vector3.uniformRing(0.1, 1.0)*10.0
)
val pr = p.rectified(0.01, 100.0)
val sphere = sphereMesh(radius = 0.1)
extend(Orbital())
extend {
drawer.stroke = ColorRGBa.PINK
for (i in 0 until 500) {
drawer.isolated {
drawer.translate(pr.position(i / 499.0))
drawer.vertexBuffer(sphere, DrawPrimitive.TRIANGLES)
}
}
val pr = p.rectified(0.01, 100.0)
val sphere = sphereMesh(radius = 0.1)
extend(Orbital())
extend {
drawer.stroke = ColorRGBa.PINK
for (i in 0 until 500) {
drawer.isolated {
drawer.translate(pr.position(i/499.0))
drawer.vertexBuffer(sphere, DrawPrimitive.TRIANGLES)
}
}
drawer.path(p)
}
drawer.path(p)
}
}
}
}

View File

@@ -6,26 +6,23 @@ import org.openrndr.draw.font.loadFace
import org.openrndr.extra.shapes.bounds.bounds
import org.openrndr.extra.shapes.text.shapesFromText
fun main() {
application {
fun main() = application {
configure {
width = 720
height = 720
}
program {
configure {
width = 720
height = 720
}
program {
val face =
loadFace("https://github.com/IBM/plex/raw/master/packages/plex-mono/fonts/complete/otf/IBMPlexMono-Bold.otf")
val shapes = shapesFromText(face, "SUCH\nVECTOR\nSUCH\nTEXT", 150.0)
val face =
loadFace("https://github.com/IBM/plex/raw/master/packages/plex-mono/fonts/complete/otf/IBMPlexMono-Bold.otf")
val shapes = shapesFromText(face, "SUCH\nVECTOR\nSUCH\nTEXT", 150.0)
val bounds = shapes.bounds
extend {
drawer.clear(ColorRGBa.PINK)
drawer.translate(-bounds.corner)
drawer.translate((width - bounds.width) / 2.0, (height - bounds.height) / 2.0)
drawer.shapes(shapes)
}
val bounds = shapes.bounds
extend {
drawer.clear(ColorRGBa.PINK)
drawer.translate(-bounds.corner)
drawer.translate((width - bounds.width) / 2.0, (height - bounds.height) / 2.0)
drawer.shapes(shapes)
}
}
}

Some files were not shown because too many files have changed in this diff Show More