OPENRNDR 0.4.0 + ORX 0.4.0 released!

It took a while, it took a long while.

OPENRNDR 0.4.0 release notes:

ORX 0.4.0 release notes:

Both releases pack more than a year’s worth of features, improvements and bug fixes. There is quite a bit to unpack here.

I will start listing some of my personal favorites:

  • Improved quality of the Bezier polygon (Shape) clipper
  • The new hobbyCurve feature
  • The new Shape.scatter() feature

I will update this post with images and code! I also invite anyone to showcase their favorite 0.4.0 features!

3 Likes

:tada:

485 commits!

That’s the number of commits in this release if I counted them correctly.

Big thank you to Edwin for the huge effort and to the RNDR Studio for creating OPENRNDR and making it Free Software :slight_smile: And thanks to everyone who contributes and uses it. It makes me happy to be part of this growing family.

:zap: ApplicationPreload

This is one feature I enjoy in OPENRNDR 0.4.0. It allowed me to add screenshots, video exporting and pressing ESC to quit to hundreds of programs in a project at once, instead of repeating the code in every program.

:zap: Video export pause and resume

Adding video exporting by default required to actually not export video until I press a key (to avoid filling my drive with video files) and then be able to start, pause and resume video exporting. This is possible thanks to the screenRecorder.outputToVideo boolean.

Both features are described in Enable Screenshots, ScreenRecorder and more in all programs by default

2 Likes

:zap: Rectangle.grid() now with cell dimensions

The .grid() method makes it easy to convert a Rectangle into a List<List<Rectangle>>. Previously one could specify the number of columns and rows by using Int arguments, but with ORX 0.4.0 one can also specify the dimensions of the cells by using Double values.

This makes it easy to define cell sizes with specific aspect ratios (for example, squares). The number of resulting columns and rows is calculated by the library according to the the requested cell dimensions, gutter values and window size.

import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extra.shapes.grid

fun main() = application {
    configure {
        width = 750
        height = 250
    }

    program {
        extend {
            drawer.clear(ColorRGBa.PINK)
            drawer.fill = ColorRGBa.WHITE
            drawer.stroke = null
            drawer.bounds.grid(
                100.0, 100.0, 10.0, 10.0, 10.0, 10.0
            ).flatten().forEach {
                drawer.rectangle(it)
            }
        }
    }
}

Another example using this feature (source code).

Here a quick demo showing how myShapeContour.hobbyCurve() converts polygonal contours into smooth contours. The bézier control points are made symmetric thanks to John Hobby’s algorithm.

imports
import org.openrndr.Fullscreen
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extra.noise.Random
import org.openrndr.extra.shapes.grid
import org.openrndr.extra.shapes.hobbyCurve
import org.openrndr.math.Polar
import org.openrndr.shape.ShapeContour
fun main() = application {
    configure {
        fullscreen = Fullscreen.CURRENT_DISPLAY_MODE
    }
    program {
        extend {
            Random.seed = "bkwd"
            drawer.clear(ColorRGBa.WHITE)
            drawer.bounds.grid(4, 4, 50.0, 50.0, 50.0, 50.0).flatten().forEachIndexed { i, rect ->
                val count = i + 2
                // points with even angular spacing and randomized radius
                val points = List(count) {
                    rect.center + Polar(it * 360.0 / count, rect.width * Random.double(0.1, 0.4)).cartesian
                }
                val pointyContour = ShapeContour.fromPoints(points, true)
                val smoothContour = pointyContour.hobbyCurve()

                drawer.fill = ColorRGBa.PINK
                drawer.contour(smoothContour)

                drawer.stroke = ColorRGBa.BLACK.opacify(0.4)
                drawer.fill = ColorRGBa.BLACK.opacify(0.2)
                drawer.contour(pointyContour)

                drawer.fill = ColorRGBa.RED
                drawer.circles(points, 5.0)
            }
        }
    }
}

Another new feature mentioned by Edwin above is the Shape.scatter() function, which allows to fill shapes with 2D points while keeping the specified distance to other points and to the edge of the shape.

imports
import org.openrndr.application
import org.openrndr.color.ColorRGBa
import org.openrndr.extra.noise.scatter
import org.openrndr.extra.shapes.hobbyCurve
import org.openrndr.math.Polar
import org.openrndr.shape.ShapeContour
fun main() = application {
    program {
        val star = ShapeContour.fromPoints(List(15) {
            Polar(it * 360.0 / 15.0, (it % 3) * 100.0 + 100.0).cartesian
        }, true).hobbyCurve().shape

        val points = star.scatter(placementRadius = 20.0, distanceToEdge = 30.0)

        extend {
            drawer.clear(ColorRGBa.WHITE)
            drawer.translate(drawer.bounds.center)
            drawer.stroke = null

            drawer.fill = ColorRGBa.PINK
            drawer.shape(star)

            drawer.fill = ColorRGBa.WHITE
            drawer.circles(points, 16.0)
        }
    }
}