Compare commits
7 Commits
816e954ed8
...
0d15c60606
| Author | SHA1 | Date | |
|---|---|---|---|
| 0d15c60606 | |||
| ac86ab3976 | |||
|
|
3ba0395c16 | ||
|
|
10888b0e83 | ||
|
|
6024e62af0 | ||
|
|
4af2ed3fed | ||
|
|
522627ca51 |
@@ -61,6 +61,9 @@ dependencies {
|
|||||||
implementation(project(":orx-palette")) {
|
implementation(project(":orx-palette")) {
|
||||||
exclude(group = "org.openrndr", module = "openrndr-draw")
|
exclude(group = "org.openrndr", module = "openrndr-draw")
|
||||||
}
|
}
|
||||||
|
implementation(project(":orx-shapes")) {
|
||||||
|
exclude(group = "org.openrndr", module = "openrndr-draw")
|
||||||
|
}
|
||||||
|
|
||||||
testImplementation(libs.junit)
|
testImplementation(libs.junit)
|
||||||
androidTestImplementation(libs.ext.junit)
|
androidTestImplementation(libs.ext.junit)
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import com.icegps.orx.ktx.area
|
|||||||
import com.icegps.orx.ktx.toColorInt
|
import com.icegps.orx.ktx.toColorInt
|
||||||
import com.icegps.orx.ktx.toMapboxPoint
|
import com.icegps.orx.ktx.toMapboxPoint
|
||||||
import com.icegps.orx.ktx.toast
|
import com.icegps.orx.ktx.toast
|
||||||
|
import com.icegps.orx.triangulation.DelaunayTriangulation3D
|
||||||
|
import com.icegps.orx.triangulation.Triangle3D
|
||||||
import com.icegps.shared.ktx.TAG
|
import com.icegps.shared.ktx.TAG
|
||||||
import com.mapbox.geojson.Feature
|
import com.mapbox.geojson.Feature
|
||||||
import com.mapbox.geojson.FeatureCollection
|
import com.mapbox.geojson.FeatureCollection
|
||||||
@@ -30,8 +32,7 @@ import kotlinx.coroutines.async
|
|||||||
import kotlinx.coroutines.awaitAll
|
import kotlinx.coroutines.awaitAll
|
||||||
import kotlinx.coroutines.launch
|
import kotlinx.coroutines.launch
|
||||||
import kotlinx.coroutines.withContext
|
import kotlinx.coroutines.withContext
|
||||||
import com.icegps.orx.triangulation.DelaunayTriangulation3D
|
import org.openrndr.extra.shapes.splines.CatmullRomChain2
|
||||||
import com.icegps.orx.triangulation.Triangle3D
|
|
||||||
import org.openrndr.math.Vector2
|
import org.openrndr.math.Vector2
|
||||||
import org.openrndr.math.Vector3
|
import org.openrndr.math.Vector3
|
||||||
import org.openrndr.shape.Rectangle
|
import org.openrndr.shape.Rectangle
|
||||||
@@ -294,10 +295,21 @@ class ContoursManager(
|
|||||||
style.addLayer(layer)
|
style.addLayer(layer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var useCatmullRom: Boolean = true
|
||||||
|
|
||||||
|
fun setCatmullRom(enabled: Boolean) {
|
||||||
|
useCatmullRom = enabled
|
||||||
|
}
|
||||||
|
|
||||||
fun contoursToLineFeatures(contours: List<ShapeContour>, color: Int): List<List<Feature>> {
|
fun contoursToLineFeatures(contours: List<ShapeContour>, color: Int): List<List<Feature>> {
|
||||||
return contours.drop(1).map { contour ->
|
return contours.drop(1).map { contour ->
|
||||||
contour.segments.map { segment ->
|
contour.segments.map { segment ->
|
||||||
LineString.fromLngLats(listOf(segment.start.toMapboxPoint(), segment.end.toMapboxPoint()))
|
LineString.fromLngLats(
|
||||||
|
listOf(
|
||||||
|
segment.start.toMapboxPoint(),
|
||||||
|
segment.end.toMapboxPoint()
|
||||||
|
)
|
||||||
|
)
|
||||||
}.map { lineString ->
|
}.map { lineString ->
|
||||||
Feature.fromGeometry(lineString).apply {
|
Feature.fromGeometry(lineString).apply {
|
||||||
// 将颜色Int转换为十六进制字符串
|
// 将颜色Int转换为十六进制字符串
|
||||||
@@ -311,6 +323,12 @@ class ContoursManager(
|
|||||||
val lists = contours.drop(0).filter { it.segments.isNotEmpty() }.map { contour ->
|
val lists = contours.drop(0).filter { it.segments.isNotEmpty() }.map { contour ->
|
||||||
val start = contour.segments[0].start
|
val start = contour.segments[0].start
|
||||||
listOf(start) + contour.segments.map { it.end }
|
listOf(start) + contour.segments.map { it.end }
|
||||||
|
}.map {
|
||||||
|
if (!useCatmullRom) return@map it
|
||||||
|
val cmr = CatmullRomChain2(it, 1.0, loop = true)
|
||||||
|
val contour = ShapeContour.fromPoints(cmr.positions(200), true)
|
||||||
|
val start = contour.segments[0].start
|
||||||
|
listOf(start) + contour.segments.map { it.end }
|
||||||
}.map { points -> points.map { it.toMapboxPoint() } }
|
}.map { points -> points.map { it.toMapboxPoint() } }
|
||||||
|
|
||||||
if (lists.isEmpty()) {
|
if (lists.isEmpty()) {
|
||||||
|
|||||||
117
android/src/main/res/layout-port/activity_main.xml
Normal file
117
android/src/main/res/layout-port/activity_main.xml
Normal file
@@ -0,0 +1,117 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:id="@+id/main"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:orientation="vertical"
|
||||||
|
tools:context=".MainActivity">
|
||||||
|
|
||||||
|
<com.mapbox.maps.MapView
|
||||||
|
android:id="@+id/map_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="3" />
|
||||||
|
|
||||||
|
<ScrollView
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
android:layout_weight="1">
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<com.google.android.material.slider.Slider
|
||||||
|
android:id="@+id/slider_target_height"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:value="0"
|
||||||
|
android:valueFrom="0"
|
||||||
|
android:valueTo="100" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="栅格大小:" />
|
||||||
|
|
||||||
|
<com.google.android.material.slider.Slider
|
||||||
|
android:id="@+id/cell_size"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:value="1"
|
||||||
|
android:valueFrom="1"
|
||||||
|
android:valueTo="100" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:orientation="horizontal">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="高度范围:" />
|
||||||
|
|
||||||
|
<com.google.android.material.slider.RangeSlider
|
||||||
|
android:id="@+id/height_range"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:valueFrom="0"
|
||||||
|
android:valueTo="100" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<Switch
|
||||||
|
android:id="@+id/switch_grid"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:switchPadding="16dp"
|
||||||
|
android:text="栅格网" />
|
||||||
|
|
||||||
|
<Switch
|
||||||
|
android:id="@+id/switch_triangle"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:switchPadding="16dp"
|
||||||
|
android:text="三角网" />
|
||||||
|
|
||||||
|
<LinearLayout
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="坐标数量:" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/point_count"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/update"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="刷新界面" />
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/clear_points"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="清除所有点" />
|
||||||
|
</LinearLayout>
|
||||||
|
</ScrollView>
|
||||||
|
</LinearLayout>
|
||||||
@@ -132,7 +132,7 @@ abstract class CollectScreenshotsTask @Inject constructor() : DefaultTask() {
|
|||||||
val codeLines = ktFile.readLines()
|
val codeLines = ktFile.readLines()
|
||||||
val main = codeLines.indexOfFirst { it.startsWith("fun main") }
|
val main = codeLines.indexOfFirst { it.startsWith("fun main") }
|
||||||
val head = codeLines.take(main)
|
val head = codeLines.take(main)
|
||||||
val start = head.indexOfLast { it.startsWith("/**") }
|
val start = head.indexOfLast { it.startsWith("/*") }
|
||||||
val end = head.indexOfLast { it.endsWith("*/") }
|
val end = head.indexOfLast { it.endsWith("*/") }
|
||||||
|
|
||||||
if ((start < end) && (end < main)) {
|
if ((start < end) && (end < main)) {
|
||||||
|
|||||||
@@ -51,7 +51,12 @@ Two color spaces are added: `ColorHSLUVa` and `ColorHPLUVa`, they are an impleme
|
|||||||
## Demos
|
## Demos
|
||||||
### colormap/DemoSpectralZucconiColormap
|
### colormap/DemoSpectralZucconiColormap
|
||||||
|
|
||||||
|
This program demonstrates the `spectralZucconi6()` function, which
|
||||||
|
takes a normalized value and returns a `ColorRGBa` using the
|
||||||
|
accurate spectral colormap developed by Alan Zucconi.
|
||||||
|
|
||||||
|
It draws a varying number of vertical bands (between 16 and 48)
|
||||||
|
filled with various hues.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -59,7 +64,13 @@ Two color spaces are added: `ColorHSLUVa` and `ColorHPLUVa`, they are an impleme
|
|||||||
|
|
||||||
### colormap/DemoSpectralZucconiColormapPhrase
|
### colormap/DemoSpectralZucconiColormapPhrase
|
||||||
|
|
||||||
|
This program demonstrates how to use the shader-based version of
|
||||||
|
the `spectral_zucconi6()` function, which
|
||||||
|
takes a normalized value and returns an `rgb` color using the
|
||||||
|
accurate spectral colormap developed by Alan Zucconi.
|
||||||
|
|
||||||
|
It shades a full-window rectangle using its normalized `x` coordinate
|
||||||
|
in a `ShadeStyle` to choose pixel colors.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -67,7 +78,11 @@ Two color spaces are added: `ColorHSLUVa` and `ColorHPLUVa`, they are an impleme
|
|||||||
|
|
||||||
### colormap/DemoSpectralZucconiColormapPlot
|
### colormap/DemoSpectralZucconiColormapPlot
|
||||||
|
|
||||||
|
This demo uses the shader based `spectral_zucconi6()` function to fill the background,
|
||||||
|
then visualizes the red, green and blue components of the colors used in the background
|
||||||
|
as red, green and blue line strips.
|
||||||
|
|
||||||
|
The Vector2 points for the line strips are calculated only once when the program starts.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -75,7 +90,12 @@ Two color spaces are added: `ColorHSLUVa` and `ColorHPLUVa`, they are an impleme
|
|||||||
|
|
||||||
### colormap/DemoTurboColormap
|
### colormap/DemoTurboColormap
|
||||||
|
|
||||||
|
This program demonstrates the `turboColormap()` function, which
|
||||||
|
takes a normalized value and returns a `ColorRGBa` using the
|
||||||
|
Turbo colormap developed by Google.
|
||||||
|
|
||||||
|
It draws a varying number of vertical bands (between 16 and 48)
|
||||||
|
filled with various hues.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -83,7 +103,13 @@ Two color spaces are added: `ColorHSLUVa` and `ColorHPLUVa`, they are an impleme
|
|||||||
|
|
||||||
### colormap/DemoTurboColormapPhrase
|
### colormap/DemoTurboColormapPhrase
|
||||||
|
|
||||||
|
This program demonstrates how to use the shader-based version of
|
||||||
|
the `turbo_colormap()` function, which
|
||||||
|
takes a normalized value and returns an `rgb` color using the
|
||||||
|
Turbo colormap developed by Google.
|
||||||
|
|
||||||
|
It shades a full-window rectangle using its normalized `x` coordinate
|
||||||
|
in a `ShadeStyle` to choose pixel colors.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -91,7 +117,11 @@ Two color spaces are added: `ColorHSLUVa` and `ColorHPLUVa`, they are an impleme
|
|||||||
|
|
||||||
### colormap/DemoTurboColormapPlot
|
### colormap/DemoTurboColormapPlot
|
||||||
|
|
||||||
|
This demo uses the shader based `turbo_colormap()` function to fill the background,
|
||||||
|
then visualizes the red, green and blue components of the colors used in the background
|
||||||
|
as red, green and blue line strips.
|
||||||
|
|
||||||
|
The Vector2 points for the line strips are calculated only once when the program starts.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -171,7 +201,8 @@ to position the images dynamically based on their index within the grid.
|
|||||||
|
|
||||||
### colorRange/DemoColorRange01
|
### colorRange/DemoColorRange01
|
||||||
|
|
||||||
|
Comparison of color lists generated by interpolating from
|
||||||
|
`PINK` to `BLUE` in six different color spaces.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -179,7 +210,13 @@ to position the images dynamically based on their index within the grid.
|
|||||||
|
|
||||||
### colorRange/DemoColorRange02
|
### colorRange/DemoColorRange02
|
||||||
|
|
||||||
|
Demonstrates how to create a `ColorSequence` containing three colors, one of them in the HSLUV color space.
|
||||||
|
|
||||||
|
Each color in the sequence is assigned a normalized position: in this program, one at the start (0.0),
|
||||||
|
one in the middle (0.5) and one at the end (1.0).
|
||||||
|
|
||||||
|
The `ColorSpace.blend()` method is used to get a list with 18 interpolated `ColorRGBa` colors,
|
||||||
|
then those colors are drawn as vertical rectangles covering the whole window.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -187,7 +224,13 @@ to position the images dynamically based on their index within the grid.
|
|||||||
|
|
||||||
### colorRange/DemoColorRange03
|
### colorRange/DemoColorRange03
|
||||||
|
|
||||||
|
This program creates color interpolations from `ColorRGBa.BLUE` to
|
||||||
|
`ColorRGBa.PINK` in 25 steps in multiple color spaces.
|
||||||
|
|
||||||
|
The window height is adjusted based on the number of interpolations to show.
|
||||||
|
|
||||||
|
The resulting gradients differ in saturation and brightness and apparently include more
|
||||||
|
`BLUE` or more `PINK` depending on the chosen color space.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -195,6 +238,17 @@ to position the images dynamically based on their index within the grid.
|
|||||||
|
|
||||||
### colorRange/DemoColorRange04
|
### colorRange/DemoColorRange04
|
||||||
|
|
||||||
|
A visualization of color interpolations inside a 3D RGB cube with an interactive 3D `Orbital` camera.
|
||||||
|
|
||||||
|
The hues of the source and target colors are animated over time.
|
||||||
|
|
||||||
|
The color interpolations are shown simultaneously in nine different color spaces, revealing how in
|
||||||
|
each case they share common starting and ending points in 3D, but have unique paths going from
|
||||||
|
start to end.
|
||||||
|
|
||||||
|
By rotating the cube 90 degrees towards the left and slightly zooming out, one can appreciate how
|
||||||
|
one of the points moves along the edges of the cube, while the other moves on the edges of a
|
||||||
|
smaller, invisible cube.
|
||||||
|
|
||||||
|
|
||||||

|

|
||||||
@@ -337,13 +391,6 @@ The rendering process includes:
|
|||||||
|
|
||||||
### histogram/DemoHistogram01
|
### histogram/DemoHistogram01
|
||||||
|
|
||||||
package histogram
|
|
||||||
|
|
||||||
import org.openrndr.application
|
|
||||||
import org.openrndr.draw.loadImage
|
|
||||||
import org.openrndr.extra.color.statistics.calculateHistogramRGB
|
|
||||||
|
|
||||||
/*
|
|
||||||
Demonstrates how to generate a palette with the top 32 colors
|
Demonstrates how to generate a palette with the top 32 colors
|
||||||
of a loaded image, sorted by luminosity. The colors are displayed
|
of a loaded image, sorted by luminosity. The colors are displayed
|
||||||
as rectangles overlayed on top of the image.
|
as rectangles overlayed on top of the image.
|
||||||
@@ -354,14 +401,6 @@ as rectangles overlayed on top of the image.
|
|||||||
|
|
||||||
### histogram/DemoHistogram02
|
### histogram/DemoHistogram02
|
||||||
|
|
||||||
package histogram
|
|
||||||
|
|
||||||
import org.openrndr.application
|
|
||||||
import org.openrndr.draw.loadImage
|
|
||||||
import org.openrndr.extra.color.statistics.calculateHistogramRGB
|
|
||||||
import kotlin.math.pow
|
|
||||||
|
|
||||||
/*
|
|
||||||
Show the color histogram of an image using non-uniform weighting,
|
Show the color histogram of an image using non-uniform weighting,
|
||||||
prioritizing bright colors.
|
prioritizing bright colors.
|
||||||
|
|
||||||
@@ -371,13 +410,6 @@ prioritizing bright colors.
|
|||||||
|
|
||||||
### histogram/DemoHistogram03
|
### histogram/DemoHistogram03
|
||||||
|
|
||||||
package histogram
|
|
||||||
|
|
||||||
import org.openrndr.application
|
|
||||||
import org.openrndr.draw.loadImage
|
|
||||||
import org.openrndr.extra.color.statistics.calculateHistogramRGB
|
|
||||||
|
|
||||||
/*
|
|
||||||
Create a simple grid-like composition based on colors sampled from image.
|
Create a simple grid-like composition based on colors sampled from image.
|
||||||
The cells are 32 by 32 pixels in size and are filled with a random sample
|
The cells are 32 by 32 pixels in size and are filled with a random sample
|
||||||
taken from the color histogram of the image.
|
taken from the color histogram of the image.
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
package colorRange
|
package colorRange
|
||||||
|
|
||||||
// Comparison of color lists generated by interpolating from
|
|
||||||
// PINK to BLUE in different color models
|
|
||||||
|
|
||||||
import org.openrndr.application
|
import org.openrndr.application
|
||||||
import org.openrndr.color.ColorRGBa
|
import org.openrndr.color.ColorRGBa
|
||||||
import org.openrndr.extra.color.palettes.rangeTo
|
import org.openrndr.extra.color.palettes.rangeTo
|
||||||
@@ -11,6 +8,10 @@ import org.openrndr.math.Vector2
|
|||||||
import org.openrndr.math.map
|
import org.openrndr.math.map
|
||||||
import org.openrndr.shape.Rectangle
|
import org.openrndr.shape.Rectangle
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Comparison of color lists generated by interpolating from
|
||||||
|
* `PINK` to `BLUE` in six different color spaces.
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
configure {
|
configure {
|
||||||
width = 720
|
width = 720
|
||||||
|
|||||||
@@ -1,12 +1,19 @@
|
|||||||
package colorRange
|
package colorRange
|
||||||
|
|
||||||
// Create a colorSequence with multiple color models
|
|
||||||
|
|
||||||
import org.openrndr.application
|
import org.openrndr.application
|
||||||
import org.openrndr.color.ColorRGBa
|
import org.openrndr.color.ColorRGBa
|
||||||
import org.openrndr.extra.color.palettes.colorSequence
|
import org.openrndr.extra.color.palettes.colorSequence
|
||||||
import org.openrndr.extra.color.spaces.toHSLUVa
|
import org.openrndr.extra.color.spaces.toHSLUVa
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates how to create a `ColorSequence` containing three colors, one of them in the HSLUV color space.
|
||||||
|
*
|
||||||
|
* Each color in the sequence is assigned a normalized position: in this program, one at the start (0.0),
|
||||||
|
* one in the middle (0.5) and one at the end (1.0).
|
||||||
|
*
|
||||||
|
* The `ColorSpace.blend()` method is used to get a list with 18 interpolated `ColorRGBa` colors,
|
||||||
|
* then those colors are drawn as vertical rectangles covering the whole window.
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
configure {
|
configure {
|
||||||
width = 720
|
width = 720
|
||||||
@@ -14,14 +21,16 @@ fun main() = application {
|
|||||||
}
|
}
|
||||||
program {
|
program {
|
||||||
extend {
|
extend {
|
||||||
val cs = colorSequence(0.0 to ColorRGBa.PINK,
|
val cs = colorSequence(
|
||||||
0.5 to ColorRGBa.BLUE,
|
0.0 to ColorRGBa.PINK,
|
||||||
1.0 to ColorRGBa.PINK.toHSLUVa()) // <-- note this one is in hsluv
|
0.5 to ColorRGBa.BLUE,
|
||||||
|
1.0 to ColorRGBa.PINK.toHSLUVa() // <-- note this color is in HSLUV
|
||||||
|
)
|
||||||
|
|
||||||
for (c in cs blend (width / 40)) {
|
for (c in cs blend (width / 40)) {
|
||||||
drawer.fill = c
|
drawer.fill = c
|
||||||
drawer.stroke = null
|
drawer.stroke = null
|
||||||
drawer.rectangle(0.0, 0.0, 40.0, height.toDouble())
|
drawer.rectangle(0.0, 0.0, 40.0, height.toDouble())
|
||||||
drawer.translate(40.0, 0.0)
|
drawer.translate(40.0, 0.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,36 +6,43 @@ import org.openrndr.draw.loadFont
|
|||||||
import org.openrndr.extra.color.palettes.rangeTo
|
import org.openrndr.extra.color.palettes.rangeTo
|
||||||
import org.openrndr.extra.color.spaces.*
|
import org.openrndr.extra.color.spaces.*
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This program creates color interpolations from `ColorRGBa.BLUE` to
|
||||||
|
* `ColorRGBa.PINK` in 25 steps in multiple color spaces.
|
||||||
|
*
|
||||||
|
* The window height is adjusted based on the number of interpolations to show.
|
||||||
|
*
|
||||||
|
* The resulting gradients differ in saturation and brightness and apparently include more
|
||||||
|
* `BLUE` or more `PINK` depending on the chosen color space.
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
|
val colorA = ColorRGBa.BLUE
|
||||||
|
val colorB = ColorRGBa.PINK
|
||||||
|
|
||||||
|
val stepCount = 25
|
||||||
|
|
||||||
|
val allSteps = listOf(
|
||||||
|
"RGB" to (colorA..colorB blend stepCount),
|
||||||
|
"RGB linear" to (colorA.toLinear()..colorB.toLinear() blend stepCount),
|
||||||
|
"HSV" to (colorA..colorB.toHSVa() blend stepCount),
|
||||||
|
"Lab" to (colorA.toLABa()..colorB.toLABa() blend stepCount),
|
||||||
|
"LCh(ab)" to (colorA.toLCHABa()..colorB.toLCHABa() blend stepCount),
|
||||||
|
"OKLab" to (colorA.toOKLABa()..colorB.toOKLABa() blend stepCount),
|
||||||
|
"OKLCh" to (colorA.toOKLCHa()..colorB.toOKLCHa() blend stepCount),
|
||||||
|
"OKHSV" to (colorA.toOKHSVa()..colorB.toOKHSVa() blend stepCount),
|
||||||
|
"OKHSL" to (colorA.toOKHSLa()..colorB.toOKHSLa() blend stepCount),
|
||||||
|
"HSLUV" to (colorA.toHSLUVa()..colorB.toHSLUVa() blend stepCount),
|
||||||
|
"XSLUV" to (colorA.toXSLUVa()..colorB.toXSLUVa() blend stepCount),
|
||||||
|
)
|
||||||
|
|
||||||
configure {
|
configure {
|
||||||
width = 720
|
width = 720
|
||||||
height = 30 + 50 * 11 // row count
|
height = 30 + 50 * allSteps.size
|
||||||
}
|
}
|
||||||
program {
|
program {
|
||||||
extend {
|
extend {
|
||||||
drawer.clear(ColorRGBa.WHITE)
|
drawer.clear(ColorRGBa.WHITE)
|
||||||
|
|
||||||
val colorA = ColorRGBa.BLUE
|
|
||||||
val colorB = ColorRGBa.PINK
|
|
||||||
|
|
||||||
val stepCount = 25
|
|
||||||
|
|
||||||
val allSteps = listOf(
|
|
||||||
"RGB" to (colorA..colorB blend stepCount),
|
|
||||||
"RGB linear" to (colorA.toLinear()..colorB.toLinear() blend stepCount),
|
|
||||||
"HSV" to (colorA..colorB.toHSVa() blend stepCount),
|
|
||||||
"Lab" to (colorA.toLABa()..colorB.toLABa() blend stepCount),
|
|
||||||
"LCh(ab)" to (colorA.toLCHABa()..colorB.toLCHABa() blend stepCount),
|
|
||||||
"OKLab" to (colorA.toOKLABa()..colorB.toOKLABa() blend stepCount),
|
|
||||||
"OKLCh" to (colorA.toOKLCHa()..colorB.toOKLCHa() blend stepCount),
|
|
||||||
"OKHSV" to (colorA.toOKHSVa()..colorB.toOKHSVa() blend stepCount),
|
|
||||||
"OKHSL" to (colorA.toOKHSLa()..colorB.toOKHSLa() blend stepCount),
|
|
||||||
"HSLUV" to (colorA.toHSLUVa()..colorB.toHSLUVa() blend stepCount),
|
|
||||||
"XSLUV" to (colorA.toXSLUVa()..colorB.toXSLUVa() blend stepCount),
|
|
||||||
)
|
|
||||||
|
|
||||||
drawer.stroke = null
|
drawer.stroke = null
|
||||||
|
|
||||||
drawer.fontMap = loadFont("demo-data/fonts/IBMPlexMono-Regular.ttf", 16.0)
|
drawer.fontMap = loadFont("demo-data/fonts/IBMPlexMono-Regular.ttf", 16.0)
|
||||||
drawer.translate(20.0, 20.0)
|
drawer.translate(20.0, 20.0)
|
||||||
for ((label, steps) in allSteps) {
|
for ((label, steps) in allSteps) {
|
||||||
|
|||||||
@@ -14,6 +14,20 @@ import org.openrndr.extra.color.spaces.toXSLUVa
|
|||||||
import org.openrndr.extra.meshgenerators.sphereMesh
|
import org.openrndr.extra.meshgenerators.sphereMesh
|
||||||
import org.openrndr.math.Vector3
|
import org.openrndr.math.Vector3
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A visualization of color interpolations inside a 3D RGB cube with an interactive 3D `Orbital` camera.
|
||||||
|
*
|
||||||
|
* The hues of the source and target colors are animated over time.
|
||||||
|
*
|
||||||
|
* The color interpolations are shown simultaneously in nine different color spaces, revealing how in
|
||||||
|
* each case they share common starting and ending points in 3D, but have unique paths going from
|
||||||
|
* start to end.
|
||||||
|
*
|
||||||
|
* By rotating the cube 90 degrees towards the left and slightly zooming out, one can appreciate how
|
||||||
|
* one of the points moves along the edges of the cube, while the other moves on the edges of a
|
||||||
|
* smaller, invisible cube.
|
||||||
|
*
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
configure {
|
configure {
|
||||||
width = 720
|
width = 720
|
||||||
@@ -44,9 +58,6 @@ fun main() = application {
|
|||||||
"XSLUV" to (colorA.toXSLUVa()..colorB.toXSLUVa() blend stepCount),
|
"XSLUV" to (colorA.toXSLUVa()..colorB.toXSLUVa() blend stepCount),
|
||||||
)
|
)
|
||||||
|
|
||||||
drawer.stroke = null
|
|
||||||
|
|
||||||
drawer.fontMap = loadFont("demo-data/fonts/IBMPlexMono-Regular.ttf", 16.0)
|
|
||||||
for ((_, steps) in allSteps) {
|
for ((_, steps) in allSteps) {
|
||||||
for (i in steps.indices) {
|
for (i in steps.indices) {
|
||||||
val srgb = steps[i].toSRGB().clip()
|
val srgb = steps[i].toSRGB().clip()
|
||||||
|
|||||||
@@ -5,6 +5,14 @@ import org.openrndr.extra.color.colormaps.spectralZucconi6
|
|||||||
import org.openrndr.extra.noise.fastFloor
|
import org.openrndr.extra.noise.fastFloor
|
||||||
import kotlin.math.sin
|
import kotlin.math.sin
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This program demonstrates the `spectralZucconi6()` function, which
|
||||||
|
* takes a normalized value and returns a `ColorRGBa` using the
|
||||||
|
* accurate spectral colormap developed by Alan Zucconi.
|
||||||
|
*
|
||||||
|
* It draws a varying number of vertical bands (between 16 and 48)
|
||||||
|
* filled with various hues.
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
configure {
|
configure {
|
||||||
width = 720
|
width = 720
|
||||||
@@ -14,12 +22,13 @@ fun main() = application {
|
|||||||
extend {
|
extend {
|
||||||
drawer.stroke = null
|
drawer.stroke = null
|
||||||
val stripeCount = 32 + (sin(seconds) * 16.0).fastFloor()
|
val stripeCount = 32 + (sin(seconds) * 16.0).fastFloor()
|
||||||
|
val bandWidth = width / stripeCount.toDouble()
|
||||||
repeat(stripeCount) { i ->
|
repeat(stripeCount) { i ->
|
||||||
drawer.fill = spectralZucconi6(i / stripeCount.toDouble())
|
drawer.fill = spectralZucconi6(i / stripeCount.toDouble())
|
||||||
drawer.rectangle(
|
drawer.rectangle(
|
||||||
x = i * width / stripeCount.toDouble(),
|
x = i * bandWidth,
|
||||||
y = 0.0,
|
y = 0.0,
|
||||||
width = width / stripeCount.toDouble(),
|
width = bandWidth,
|
||||||
height = height.toDouble(),
|
height = height.toDouble(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,15 @@ import org.openrndr.draw.shadeStyle
|
|||||||
import org.openrndr.extra.color.colormaps.ColormapPhraseBook
|
import org.openrndr.extra.color.colormaps.ColormapPhraseBook
|
||||||
import org.openrndr.extra.shaderphrases.preprocess
|
import org.openrndr.extra.shaderphrases.preprocess
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This program demonstrates how to use the shader-based version of
|
||||||
|
* the `spectral_zucconi6()` function, which
|
||||||
|
* takes a normalized value and returns an `rgb` color using the
|
||||||
|
* accurate spectral colormap developed by Alan Zucconi.
|
||||||
|
*
|
||||||
|
* It shades a full-window rectangle using its normalized `x` coordinate
|
||||||
|
* in a `ShadeStyle` to choose pixel colors.
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
configure {
|
configure {
|
||||||
width = 720
|
width = 720
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ import org.openrndr.extra.color.colormaps.spectralZucconi6
|
|||||||
import org.openrndr.extra.shaderphrases.preprocess
|
import org.openrndr.extra.shaderphrases.preprocess
|
||||||
import org.openrndr.math.Vector2
|
import org.openrndr.math.Vector2
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This demo uses the shader based `spectral_zucconi6()` function to fill the background,
|
||||||
|
* then visualizes the red, green and blue components of the colors used in the background
|
||||||
|
* as red, green and blue line strips.
|
||||||
|
*
|
||||||
|
* The Vector2 points for the line strips are calculated only once when the program starts.
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
configure {
|
configure {
|
||||||
width = 720
|
width = 720
|
||||||
@@ -20,14 +27,14 @@ fun main() = application {
|
|||||||
fragmentTransform = "x_fill.rgb = spectral_zucconi6(c_boundsPosition.x);"
|
fragmentTransform = "x_fill.rgb = spectral_zucconi6(c_boundsPosition.x);"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Function that expects as an argument a function to convert a ColorRGBa into a Double,
|
||||||
|
// and returns a list of Vector2 coordinates.
|
||||||
fun getColormapPoints(
|
fun getColormapPoints(
|
||||||
block: ColorRGBa.() -> Double
|
block: ColorRGBa.() -> Double
|
||||||
) = List(width) { x ->
|
) = List(width) { x ->
|
||||||
Vector2(
|
Vector2(
|
||||||
x.toDouble(),
|
x.toDouble(),
|
||||||
height.toDouble()
|
(1.0 - block(spectralZucconi6(x / width.toDouble()))) * height
|
||||||
- block(spectralZucconi6(x / width.toDouble()))
|
|
||||||
* height.toDouble()
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -39,11 +46,13 @@ fun main() = application {
|
|||||||
shadeStyle = backgroundStyle
|
shadeStyle = backgroundStyle
|
||||||
rectangle(bounds)
|
rectangle(bounds)
|
||||||
shadeStyle = null
|
shadeStyle = null
|
||||||
strokeWeight = 1.0
|
|
||||||
stroke = ColorRGBa.RED
|
stroke = ColorRGBa.RED
|
||||||
lineStrip(redPoints)
|
lineStrip(redPoints)
|
||||||
|
|
||||||
stroke = ColorRGBa.GREEN
|
stroke = ColorRGBa.GREEN
|
||||||
lineStrip(greenPoints)
|
lineStrip(greenPoints)
|
||||||
|
|
||||||
stroke = ColorRGBa.BLUE
|
stroke = ColorRGBa.BLUE
|
||||||
lineStrip(bluePoints)
|
lineStrip(bluePoints)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,15 @@ import org.openrndr.extra.color.colormaps.turboColormap
|
|||||||
import org.openrndr.extra.noise.fastFloor
|
import org.openrndr.extra.noise.fastFloor
|
||||||
import kotlin.math.sin
|
import kotlin.math.sin
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This program demonstrates the `turboColormap()` function, which
|
||||||
|
* takes a normalized value and returns a `ColorRGBa` using the
|
||||||
|
* Turbo colormap developed by Google.
|
||||||
|
*
|
||||||
|
* It draws a varying number of vertical bands (between 16 and 48)
|
||||||
|
* filled with various hues.
|
||||||
|
*/
|
||||||
|
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
configure {
|
configure {
|
||||||
width = 720
|
width = 720
|
||||||
|
|||||||
@@ -5,6 +5,15 @@ import org.openrndr.draw.shadeStyle
|
|||||||
import org.openrndr.extra.color.colormaps.ColormapPhraseBook
|
import org.openrndr.extra.color.colormaps.ColormapPhraseBook
|
||||||
import org.openrndr.extra.shaderphrases.preprocess
|
import org.openrndr.extra.shaderphrases.preprocess
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This program demonstrates how to use the shader-based version of
|
||||||
|
* the `turbo_colormap()` function, which
|
||||||
|
* takes a normalized value and returns an `rgb` color using the
|
||||||
|
* Turbo colormap developed by Google.
|
||||||
|
*
|
||||||
|
* It shades a full-window rectangle using its normalized `x` coordinate
|
||||||
|
* in a `ShadeStyle` to choose pixel colors.
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
configure {
|
configure {
|
||||||
width = 720
|
width = 720
|
||||||
|
|||||||
@@ -8,6 +8,13 @@ import org.openrndr.extra.color.colormaps.turboColormap
|
|||||||
import org.openrndr.extra.shaderphrases.preprocess
|
import org.openrndr.extra.shaderphrases.preprocess
|
||||||
import org.openrndr.math.Vector2
|
import org.openrndr.math.Vector2
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This demo uses the shader based `turbo_colormap()` function to fill the background,
|
||||||
|
* then visualizes the red, green and blue components of the colors used in the background
|
||||||
|
* as red, green and blue line strips.
|
||||||
|
*
|
||||||
|
* The Vector2 points for the line strips are calculated only once when the program starts.
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
configure {
|
configure {
|
||||||
width = 720
|
width = 720
|
||||||
@@ -23,10 +30,8 @@ fun main() = application {
|
|||||||
block: ColorRGBa.() -> Double
|
block: ColorRGBa.() -> Double
|
||||||
) = List(width) { x ->
|
) = List(width) { x ->
|
||||||
Vector2(
|
Vector2(
|
||||||
x = x.toDouble(),
|
x.toDouble(),
|
||||||
y = height.toDouble()
|
(1.0 - block(turboColormap(x / width.toDouble()))) * height
|
||||||
- block(turboColormap(x / width.toDouble()))
|
|
||||||
* height.toDouble()
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
val redPoints = getColormapPoints { r }
|
val redPoints = getColormapPoints { r }
|
||||||
@@ -37,11 +42,13 @@ fun main() = application {
|
|||||||
shadeStyle = backgroundStyle
|
shadeStyle = backgroundStyle
|
||||||
rectangle(bounds)
|
rectangle(bounds)
|
||||||
shadeStyle = null
|
shadeStyle = null
|
||||||
strokeWeight = 1.0
|
|
||||||
stroke = ColorRGBa.RED
|
stroke = ColorRGBa.RED
|
||||||
lineStrip(redPoints)
|
lineStrip(redPoints)
|
||||||
|
|
||||||
stroke = ColorRGBa.GREEN
|
stroke = ColorRGBa.GREEN
|
||||||
lineStrip(greenPoints)
|
lineStrip(greenPoints)
|
||||||
|
|
||||||
stroke = ColorRGBa.BLUE
|
stroke = ColorRGBa.BLUE
|
||||||
lineStrip(bluePoints)
|
lineStrip(bluePoints)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,16 @@ this addon provides some helper functions to convert them to OPENRNDR types:
|
|||||||
## Demos
|
## Demos
|
||||||
### DemoContours01
|
### DemoContours01
|
||||||
|
|
||||||
|
Demonstrates how to convert a PNG image into `ShapeContour`s using BoofCV.
|
||||||
|
|
||||||
|
Two helper methods help convert data types between BoofCV and OPENRNDR.
|
||||||
|
|
||||||
|
The `ColorBuffer.toGrayF32()` method converts an OPENRNDR `ColorBuffer` to `GrayF32` format,
|
||||||
|
required by BoofCV.
|
||||||
|
|
||||||
|
The `.toShapeContours()` converts BoofCV contours to OPENRNDR `ShapeContour` instances.
|
||||||
|
|
||||||
|
The resulting contours are animated zooming in and out while their colors change slowly.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -34,7 +43,8 @@ this addon provides some helper functions to convert them to OPENRNDR types:
|
|||||||
|
|
||||||
### DemoResize01
|
### DemoResize01
|
||||||
|
|
||||||
|
Demonstrates how to scale down images using the `resizeBy` BoofCV-based
|
||||||
|
method.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -42,7 +52,11 @@ this addon provides some helper functions to convert them to OPENRNDR types:
|
|||||||
|
|
||||||
### DemoResize02
|
### DemoResize02
|
||||||
|
|
||||||
|
Demonstrates how to scale down images using the `resizeTo` BoofCV-based
|
||||||
|
method.
|
||||||
|
|
||||||
|
If only the `newWidth` or the `newHeight` arguments are specified,
|
||||||
|
the resizing happens maintaining the original aspect ratio.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -50,7 +64,16 @@ this addon provides some helper functions to convert them to OPENRNDR types:
|
|||||||
|
|
||||||
### DemoSimplified01
|
### DemoSimplified01
|
||||||
|
|
||||||
|
When converting a `ColorBuffer` to `ShapeContour` instances using
|
||||||
|
`BoofCV`, simple shapes can have hundreds of segments and vertices.
|
||||||
|
|
||||||
|
This demo shows how to use the `simplify()` method to greatly
|
||||||
|
reduce the number of vertices.
|
||||||
|
|
||||||
|
Then it uses the simplified vertex lists to create smooth curves
|
||||||
|
(using `CatmullRomChain2`) and polygonal curves (using `ShapeContour.fromPoints`).
|
||||||
|
|
||||||
|
Study the console to learn about the number of segments before and after simplification.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,18 @@ import org.openrndr.draw.loadImage
|
|||||||
import kotlin.math.cos
|
import kotlin.math.cos
|
||||||
import kotlin.math.sin
|
import kotlin.math.sin
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates how to convert a PNG image into `ShapeContour`s using BoofCV.
|
||||||
|
*
|
||||||
|
* Two helper methods help convert data types between BoofCV and OPENRNDR.
|
||||||
|
*
|
||||||
|
* The `ColorBuffer.toGrayF32()` method converts an OPENRNDR `ColorBuffer` to `GrayF32` format,
|
||||||
|
* required by BoofCV.
|
||||||
|
*
|
||||||
|
* The `.toShapeContours()` converts BoofCV contours to OPENRNDR `ShapeContour` instances.
|
||||||
|
*
|
||||||
|
* The resulting contours are animated zooming in and out while their colors change slowly.
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
program {
|
program {
|
||||||
// Load an image, convert to BoofCV format using orx-boofcv
|
// Load an image, convert to BoofCV format using orx-boofcv
|
||||||
|
|||||||
@@ -2,19 +2,31 @@ import org.openrndr.application
|
|||||||
import org.openrndr.boofcv.binding.resizeBy
|
import org.openrndr.boofcv.binding.resizeBy
|
||||||
import org.openrndr.color.ColorRGBa
|
import org.openrndr.color.ColorRGBa
|
||||||
import org.openrndr.draw.loadImage
|
import org.openrndr.draw.loadImage
|
||||||
|
import org.openrndr.math.Vector2
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates how to scale down images using the `resizeBy` BoofCV-based
|
||||||
|
* method.
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
program {
|
program {
|
||||||
// Load an image, convert to BoofCV format using orx-boofcv
|
|
||||||
val input = loadImage("demo-data/images/image-001.png")
|
val input = loadImage("demo-data/images/image-001.png")
|
||||||
|
|
||||||
val scaled = input.resizeBy(0.5)
|
val scaled = input.resizeBy(0.5)
|
||||||
val scaled2 = input.resizeBy(0.25, convertToGray = true)
|
val scaled2 = input.resizeBy(0.25, convertToGray = true)
|
||||||
val scaled3 = input.resizeBy(0.1)
|
val scaled3 = input.resizeBy(0.1)
|
||||||
|
|
||||||
|
println("${input.width} x ${input.height}")
|
||||||
|
println("${scaled.width} x ${scaled.height}")
|
||||||
|
|
||||||
extend {
|
extend {
|
||||||
drawer.clear(ColorRGBa.BLACK)
|
drawer.clear(ColorRGBa.BLACK)
|
||||||
drawer.translate(0.0, (height - scaled.bounds.height) / 2.0)
|
drawer.translate(0.0, (height - scaled.bounds.height) / 2.0)
|
||||||
|
|
||||||
|
// Display the loaded image to the right of `scaled` matching its size
|
||||||
|
drawer.image(input, scaled.bounds.movedBy(Vector2.UNIT_X * scaled.bounds.width))
|
||||||
|
|
||||||
|
// Display actually scaled down versions of the loaded image
|
||||||
drawer.image(scaled)
|
drawer.image(scaled)
|
||||||
drawer.image(scaled2, scaled.bounds.width, scaled.bounds.height - scaled2.height)
|
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)
|
drawer.image(scaled3, scaled.bounds.width + scaled2.bounds.width, scaled.bounds.height - scaled3.height)
|
||||||
|
|||||||
@@ -3,17 +3,29 @@ import org.openrndr.boofcv.binding.resizeTo
|
|||||||
import org.openrndr.color.ColorRGBa
|
import org.openrndr.color.ColorRGBa
|
||||||
import org.openrndr.draw.loadImage
|
import org.openrndr.draw.loadImage
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates how to scale down images using the `resizeTo` BoofCV-based
|
||||||
|
* method.
|
||||||
|
*
|
||||||
|
* If only the `newWidth` or the `newHeight` arguments are specified,
|
||||||
|
* the resizing happens maintaining the original aspect ratio.
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
program {
|
program {
|
||||||
// Load an image, convert to BoofCV format using orx-boofcv
|
|
||||||
val input = loadImage("demo-data/images/image-001.png")
|
val input = loadImage("demo-data/images/image-001.png")
|
||||||
|
|
||||||
val scaled = input.resizeTo(input.width / 3)
|
val scaled = input.resizeTo(input.width / 3)
|
||||||
val scaled2 = input.resizeTo(newHeight = input.height / 4, convertToGray = true)
|
val scaled2 = input.resizeTo(newHeight = input.height / 4, convertToGray = true)
|
||||||
val scaled3 = input.resizeTo(input.width / 5, input.height / 5)
|
val scaled3 = input.resizeTo(input.width / 5, input.height / 5)
|
||||||
|
|
||||||
|
println("${input.width} x ${input.height}")
|
||||||
|
println("${scaled.width} x ${scaled.height}")
|
||||||
|
|
||||||
extend {
|
extend {
|
||||||
drawer.clear(ColorRGBa.BLACK)
|
drawer.clear(ColorRGBa.BLACK)
|
||||||
drawer.translate(0.0, (height - scaled.bounds.height) / 2.0)
|
drawer.translate(0.0, (height - scaled.bounds.height) / 2.0)
|
||||||
|
|
||||||
|
// Display actually scaled down versions of the loaded image
|
||||||
drawer.image(scaled)
|
drawer.image(scaled)
|
||||||
drawer.image(scaled2, scaled.bounds.width, scaled.bounds.height - scaled2.height)
|
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)
|
drawer.image(scaled3, scaled.bounds.width + scaled2.bounds.width, scaled.bounds.height - scaled3.height)
|
||||||
|
|||||||
@@ -17,6 +17,18 @@ import org.openrndr.math.Vector2
|
|||||||
import org.openrndr.shape.Rectangle
|
import org.openrndr.shape.Rectangle
|
||||||
import org.openrndr.shape.ShapeContour
|
import org.openrndr.shape.ShapeContour
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When converting a `ColorBuffer` to `ShapeContour` instances using
|
||||||
|
* `BoofCV`, simple shapes can have hundreds of segments and vertices.
|
||||||
|
*
|
||||||
|
* This demo shows how to use the `simplify()` method to greatly
|
||||||
|
* reduce the number of vertices.
|
||||||
|
*
|
||||||
|
* Then it uses the simplified vertex lists to create smooth curves
|
||||||
|
* (using `CatmullRomChain2`) and polygonal curves (using `ShapeContour.fromPoints`).
|
||||||
|
*
|
||||||
|
* Study the console to learn about the number of segments before and after simplification.
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
program {
|
program {
|
||||||
// Create a buffer where to draw something for boofcv
|
// Create a buffer where to draw something for boofcv
|
||||||
@@ -41,6 +53,7 @@ fun main() = application {
|
|||||||
rectangle(0.0, -200.0, 60.0, 60.0)
|
rectangle(0.0, -200.0, 60.0, 60.0)
|
||||||
circle(0.0, 190.0, 60.0)
|
circle(0.0, 190.0, 60.0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert the bitmap buffer into ShapeContours
|
// Convert the bitmap buffer into ShapeContours
|
||||||
val vectorized = imageToContours(rt.colorBuffer(0))
|
val vectorized = imageToContours(rt.colorBuffer(0))
|
||||||
|
|
||||||
@@ -73,8 +86,11 @@ fun main() = application {
|
|||||||
extend {
|
extend {
|
||||||
drawer.run {
|
drawer.run {
|
||||||
fill = null // ColorRGBa.PINK.opacify(0.15)
|
fill = null // ColorRGBa.PINK.opacify(0.15)
|
||||||
|
|
||||||
stroke = ColorRGBa.PINK.opacify(0.7)
|
stroke = ColorRGBa.PINK.opacify(0.7)
|
||||||
contours(polygonal)
|
contours(polygonal)
|
||||||
|
|
||||||
|
stroke = ColorRGBa.GREEN.opacify(0.7)
|
||||||
contours(smooth)
|
contours(smooth)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -178,7 +178,10 @@ import org.openrndr.extra.parameters.DoubleParameter
|
|||||||
## Demos
|
## Demos
|
||||||
### DemoAppearance01
|
### DemoAppearance01
|
||||||
|
|
||||||
A simple demonstration of a GUI for drawing some circles
|
Demonstrates how to customize the appearance of the GUI by using
|
||||||
|
`GUIAppearance()`.
|
||||||
|
|
||||||
|
In this demo, we make the GUI wider (400 pixels) and translucent.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -186,7 +189,7 @@ A simple demonstration of a GUI for drawing some circles
|
|||||||
|
|
||||||
### DemoHide01
|
### DemoHide01
|
||||||
|
|
||||||
A simple demonstration of a GUI for drawing some circles
|
Demonstrates how to hide the GUI when the mouse pointer is outside of it.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -194,15 +197,38 @@ A simple demonstration of a GUI for drawing some circles
|
|||||||
|
|
||||||
### DemoOptions01
|
### DemoOptions01
|
||||||
|
|
||||||
A simple demonstration of a GUI with a drop down menu
|
A simple demonstration of a GUI with a drop-down menu.
|
||||||
|
|
||||||
|
The entries in the drop-down menu are taken from an `enum class`.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
[source code](src/demo/kotlin/DemoOptions01.kt)
|
[source code](src/demo/kotlin/DemoOptions01.kt)
|
||||||
|
|
||||||
|
### DemoOptions02
|
||||||
|
|
||||||
|
A simple demonstration of a GUI with a drop-down menu.
|
||||||
|
|
||||||
|
The entries in the drop-down menu are taken from an `enum class`.
|
||||||
|
The `enum class` entries contain both a name (used in the drop-down)
|
||||||
|
and a `ColorRGBa` instance (used for rendering).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
[source code](src/demo/kotlin/DemoOptions02.kt)
|
||||||
|
|
||||||
### DemoPath01
|
### DemoPath01
|
||||||
|
|
||||||
|
Demonstrates how to include a button for loading images in a GUI, and how to display
|
||||||
|
the loaded image.
|
||||||
|
|
||||||
|
The program applies the `@PathParameter` annotation to a `String` variable, which gets
|
||||||
|
rendered by the GUI as an image-picker button. Note the allowed file `extensions`.
|
||||||
|
|
||||||
|
This mechanism only updates the `String` containing the path of an image file.
|
||||||
|
|
||||||
|
The `watchingImagePath()` delegate property is used to automatically load an image
|
||||||
|
when its `String` argument changes.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -210,9 +236,11 @@ A simple demonstration of a GUI with a drop down menu
|
|||||||
|
|
||||||
### DemoPresets01
|
### DemoPresets01
|
||||||
|
|
||||||
Shows how to store and retrieve in-memory gui presets.
|
Shows how to store and retrieve in-memory GUI presets,
|
||||||
|
each containing two integer values and two colors.
|
||||||
|
|
||||||
Keyboard controls:
|
Keyboard controls:
|
||||||
[Left Shift] + [0]..[9] => store current gui values to a preset
|
[Left Shift] + [0]..[9] => store current GUI values to a preset
|
||||||
[0]..[9] => recall a preset
|
[0]..[9] => recall a preset
|
||||||
|
|
||||||

|

|
||||||
@@ -221,7 +249,17 @@ Keyboard controls:
|
|||||||
|
|
||||||
### DemoSideCanvas01
|
### DemoSideCanvas01
|
||||||
|
|
||||||
A simple demonstration of a GUI for drawing some circles
|
Demonstrates the `GUI.enableSideCanvas` feature.
|
||||||
|
|
||||||
|
When set to true, the `GUI` provides a `canvas` property where one can draw.
|
||||||
|
The size of this canvas is the window size minus the GUI size.
|
||||||
|
|
||||||
|
That's why if we draw a circle at `drawer.width / 2.0` it is centered
|
||||||
|
on the `canvas`, not on the window.
|
||||||
|
|
||||||
|
This demo sets the window to resizable, so if you resize the window
|
||||||
|
you should see tha the circle stays at the center of the canvas.
|
||||||
|
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -229,7 +267,15 @@ A simple demonstration of a GUI for drawing some circles
|
|||||||
|
|
||||||
### DemoSimple01
|
### DemoSimple01
|
||||||
|
|
||||||
A simple demonstration of a GUI for drawing some circles
|
Demonstrates how to create a simple GUI with 4 inputs:
|
||||||
|
- A `ColorParameter` which creates a color picker.
|
||||||
|
- A `DoubleParameter` to control the radius of a circle.
|
||||||
|
- A `Vector2Parameter` to set the position of that circle.
|
||||||
|
- A `DoubleListParameter` which sets the radii of six circles.
|
||||||
|
|
||||||
|
The demo also shows how to use the variables controlled by the GUI
|
||||||
|
inside the program, so changes to those variables affect
|
||||||
|
the rendering in real time.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -237,6 +283,10 @@ A simple demonstration of a GUI for drawing some circles
|
|||||||
|
|
||||||
### DemoXYParameter
|
### DemoXYParameter
|
||||||
|
|
||||||
|
Demonstrates the use of the `@XYParameter` annotation applied to a `Vector2` variable.
|
||||||
|
|
||||||
|
This annotation creates an interactive XY control in a GUI that can be used to update
|
||||||
|
a `Vector2` variable. In this demo it sets the position of a circle.
|
||||||
|
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
@@ -7,7 +7,10 @@ import org.openrndr.math.Vector2
|
|||||||
import org.openrndr.shape.Circle
|
import org.openrndr.shape.Circle
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple demonstration of a GUI for drawing some circles
|
* Demonstrates how to customize the appearance of the GUI by using
|
||||||
|
* `GUIAppearance()`.
|
||||||
|
*
|
||||||
|
* In this demo, we make the GUI wider (400 pixels) and translucent.
|
||||||
*/
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
program {
|
program {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import org.openrndr.math.Vector2
|
|||||||
import org.openrndr.shape.Circle
|
import org.openrndr.shape.Circle
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple demonstration of a GUI for drawing some circles
|
* Demonstrates how to hide the GUI when the mouse pointer is outside of it.
|
||||||
*/
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
program {
|
program {
|
||||||
@@ -29,7 +29,7 @@ fun main() = application {
|
|||||||
gui.add(settings)
|
gui.add(settings)
|
||||||
extend(gui)
|
extend(gui)
|
||||||
|
|
||||||
// note we can only change the visibility after the extend
|
// note we can only change the visibility after the `extend`
|
||||||
gui.visible = false
|
gui.visible = false
|
||||||
|
|
||||||
extend {
|
extend {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import org.openrndr.window
|
|||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Demonstration of multi window GUI in the manual way
|
* Demonstration of a multi window GUI in the manual way
|
||||||
*/
|
*/
|
||||||
fun main() {
|
fun main() {
|
||||||
// skip this demo on CI
|
// skip this demo on CI
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import org.openrndr.extra.parameters.DoubleParameter
|
|||||||
import kotlin.system.exitProcess
|
import kotlin.system.exitProcess
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Demonstration of multi window GUI using WindowedGUI extension
|
* Demonstration of a multi window GUI using the `WindowedGUI` extension
|
||||||
*/
|
*/
|
||||||
fun main() {
|
fun main() {
|
||||||
// skip this demo on CI
|
// skip this demo on CI
|
||||||
|
|||||||
@@ -5,7 +5,9 @@ import org.openrndr.extra.parameters.Description
|
|||||||
import org.openrndr.extra.parameters.OptionParameter
|
import org.openrndr.extra.parameters.OptionParameter
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple demonstration of a GUI with a drop down menu
|
* A simple demonstration of a GUI with a drop-down menu.
|
||||||
|
*
|
||||||
|
* The entries in the drop-down menu are taken from an `enum class`.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
enum class BackgroundColors {
|
enum class BackgroundColors {
|
||||||
@@ -15,6 +17,10 @@ enum class BackgroundColors {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
|
configure {
|
||||||
|
width = 720
|
||||||
|
height = 360
|
||||||
|
}
|
||||||
program {
|
program {
|
||||||
val gui = GUI()
|
val gui = GUI()
|
||||||
gui.compartmentsCollapsedByDefault = false
|
gui.compartmentsCollapsedByDefault = false
|
||||||
|
|||||||
43
orx-jvm/orx-gui/src/demo/kotlin/DemoOptions02.kt
Normal file
43
orx-jvm/orx-gui/src/demo/kotlin/DemoOptions02.kt
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import org.openrndr.application
|
||||||
|
import org.openrndr.color.ColorRGBa
|
||||||
|
import org.openrndr.extra.gui.GUI
|
||||||
|
import org.openrndr.extra.parameters.Description
|
||||||
|
import org.openrndr.extra.parameters.OptionParameter
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple demonstration of a GUI with a drop-down menu.
|
||||||
|
*
|
||||||
|
* The entries in the drop-down menu are taken from an `enum class`.
|
||||||
|
* The `enum class` entries contain both a name (used in the drop-down)
|
||||||
|
* and a `ColorRGBa` instance (used for rendering).
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum class BackgroundColors2(val color: ColorRGBa) {
|
||||||
|
Pink(ColorRGBa.PINK),
|
||||||
|
Black(ColorRGBa.BLACK),
|
||||||
|
Yellow(ColorRGBa.YELLOW)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main() = application {
|
||||||
|
configure {
|
||||||
|
width = 720
|
||||||
|
height = 360
|
||||||
|
}
|
||||||
|
program {
|
||||||
|
val gui = GUI()
|
||||||
|
gui.compartmentsCollapsedByDefault = false
|
||||||
|
val settings = @Description("Settings") object {
|
||||||
|
@OptionParameter("Background color")
|
||||||
|
var option = BackgroundColors2.Pink
|
||||||
|
}
|
||||||
|
|
||||||
|
gui.add(settings)
|
||||||
|
extend(gui)
|
||||||
|
gui.onChange { name, value ->
|
||||||
|
println("$name: $value")
|
||||||
|
}
|
||||||
|
extend {
|
||||||
|
drawer.clear(settings.option.color)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,18 @@ import org.openrndr.extra.parameters.Description
|
|||||||
import org.openrndr.extra.parameters.PathParameter
|
import org.openrndr.extra.parameters.PathParameter
|
||||||
import org.openrndr.extra.propertywatchers.watchingImagePath
|
import org.openrndr.extra.propertywatchers.watchingImagePath
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates how to include a button for loading images in a GUI, and how to display
|
||||||
|
* the loaded image.
|
||||||
|
*
|
||||||
|
* The program applies the `@PathParameter` annotation to a `String` variable, which gets
|
||||||
|
* rendered by the GUI as an image-picker button. Note the allowed file `extensions`.
|
||||||
|
*
|
||||||
|
* This mechanism only updates the `String` containing the path of an image file.
|
||||||
|
*
|
||||||
|
* The `watchingImagePath()` delegate property is used to automatically load an image
|
||||||
|
* when its `String` argument changes.
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
program {
|
program {
|
||||||
val gui = GUI()
|
val gui = GUI()
|
||||||
|
|||||||
@@ -7,12 +7,18 @@ import org.openrndr.extra.parameters.Description
|
|||||||
import org.openrndr.extra.parameters.IntParameter
|
import org.openrndr.extra.parameters.IntParameter
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows how to store and retrieve in-memory gui presets.
|
* Shows how to store and retrieve in-memory GUI presets,
|
||||||
|
* each containing two integer values and two colors.
|
||||||
|
*
|
||||||
* Keyboard controls:
|
* Keyboard controls:
|
||||||
* [Left Shift] + [0]..[9] => store current gui values to a preset
|
* [Left Shift] + [0]..[9] => store current GUI values to a preset
|
||||||
* [0]..[9] => recall a preset
|
* [0]..[9] => recall a preset
|
||||||
*/
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
|
configure {
|
||||||
|
width = 720
|
||||||
|
height = 480
|
||||||
|
}
|
||||||
program {
|
program {
|
||||||
val gui = GUI()
|
val gui = GUI()
|
||||||
gui.compartmentsCollapsedByDefault = false
|
gui.compartmentsCollapsedByDefault = false
|
||||||
@@ -43,9 +49,9 @@ fun main() = application {
|
|||||||
// Draw a pattern based on modulo
|
// Draw a pattern based on modulo
|
||||||
for (i in 0 until 100) {
|
for (i in 0 until 100) {
|
||||||
if (i % settings.a == 0 || i % settings.b == 0) {
|
if (i % settings.a == 0 || i % settings.b == 0) {
|
||||||
val x = (i % 10) * 64.0
|
val x = (i % 10) * 72.0
|
||||||
val y = (i / 10) * 48.0
|
val y = (i / 10) * 48.0
|
||||||
drawer.rectangle(x, y, 64.0, 48.0)
|
drawer.rectangle(x, y, 72.0, 48.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,18 +2,29 @@ import org.openrndr.application
|
|||||||
import org.openrndr.color.ColorRGBa
|
import org.openrndr.color.ColorRGBa
|
||||||
import org.openrndr.extra.gui.GUI
|
import org.openrndr.extra.gui.GUI
|
||||||
import org.openrndr.extra.gui.GUIAppearance
|
import org.openrndr.extra.gui.GUIAppearance
|
||||||
import org.openrndr.extra.parameters.*
|
import org.openrndr.extra.parameters.ColorParameter
|
||||||
import org.openrndr.math.Vector2
|
import org.openrndr.extra.parameters.Description
|
||||||
|
import org.openrndr.extra.parameters.DoubleParameter
|
||||||
import org.openrndr.panel.elements.draw
|
import org.openrndr.panel.elements.draw
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple demonstration of a GUI for drawing some circles
|
* Demonstrates the `GUI.enableSideCanvas` feature.
|
||||||
|
*
|
||||||
|
* When set to true, the `GUI` provides a `canvas` property where one can draw.
|
||||||
|
* The size of this canvas is the window size minus the GUI size.
|
||||||
|
*
|
||||||
|
* That's why if we draw a circle at `drawer.width / 2.0` it is centered
|
||||||
|
* on the `canvas`, not on the window.
|
||||||
|
*
|
||||||
|
* This demo sets the window to resizable, so if you resize the window
|
||||||
|
* you should see tha the circle stays at the center of the canvas.
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
configure {
|
configure {
|
||||||
width = 800
|
width = 720
|
||||||
height = 800
|
height = 720
|
||||||
windowResizable = true
|
windowResizable = true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,17 +34,11 @@ fun main() = application {
|
|||||||
gui.enableSideCanvas = true
|
gui.enableSideCanvas = true
|
||||||
|
|
||||||
val settings = @Description("Settings") object {
|
val settings = @Description("Settings") object {
|
||||||
@DoubleParameter("radius", 0.0, 100.0)
|
@DoubleParameter("radius", 0.0, 200.0)
|
||||||
var radius = 50.0
|
var radius = 50.0
|
||||||
|
|
||||||
@Vector2Parameter("position", 0.0, 1.0)
|
|
||||||
var position = Vector2(0.6, 0.5)
|
|
||||||
|
|
||||||
@ColorParameter("color")
|
@ColorParameter("color")
|
||||||
var color = ColorRGBa.PINK
|
var color = ColorRGBa.PINK
|
||||||
|
|
||||||
@DoubleListParameter("radii", 5.0, 30.0)
|
|
||||||
var radii = mutableListOf(5.0, 6.0, 8.0, 14.0, 20.0, 30.0)
|
|
||||||
}
|
}
|
||||||
gui.add(settings)
|
gui.add(settings)
|
||||||
extend(gui)
|
extend(gui)
|
||||||
@@ -42,7 +47,7 @@ fun main() = application {
|
|||||||
val width = drawer.width
|
val width = drawer.width
|
||||||
val height = drawer.height
|
val height = drawer.height
|
||||||
drawer.fill = settings.color
|
drawer.fill = settings.color
|
||||||
drawer.circle(width/2.0, height/2.0, 100.0)
|
drawer.circle(width / 2.0, height / 2.0, settings.radius)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6,11 +6,22 @@ import org.openrndr.math.Vector2
|
|||||||
import org.openrndr.shape.Circle
|
import org.openrndr.shape.Circle
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A simple demonstration of a GUI for drawing some circles
|
* Demonstrates how to create a simple GUI with 4 inputs:
|
||||||
|
* - A `ColorParameter` which creates a color picker.
|
||||||
|
* - A `DoubleParameter` to control the radius of a circle.
|
||||||
|
* - A `Vector2Parameter` to set the position of that circle.
|
||||||
|
* - A `DoubleListParameter` which sets the radii of six circles.
|
||||||
|
*
|
||||||
|
* The demo also shows how to use the variables controlled by the GUI
|
||||||
|
* inside the program, so changes to those variables affect
|
||||||
|
* the rendering in real time.
|
||||||
*/
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
|
configure {
|
||||||
|
width = 720
|
||||||
|
height = 450
|
||||||
|
}
|
||||||
program {
|
program {
|
||||||
|
|
||||||
val gui = GUI()
|
val gui = GUI()
|
||||||
gui.compartmentsCollapsedByDefault = false
|
gui.compartmentsCollapsedByDefault = false
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,13 @@ import org.openrndr.extra.parameters.Description
|
|||||||
import org.openrndr.extra.parameters.XYParameter
|
import org.openrndr.extra.parameters.XYParameter
|
||||||
import org.openrndr.math.Vector2
|
import org.openrndr.math.Vector2
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates the use of the `@XYParameter` annotation applied to a `Vector2` variable.
|
||||||
|
*
|
||||||
|
* This annotation creates an interactive XY control in a GUI that can be used to update
|
||||||
|
* a `Vector2` variable. In this demo it sets the position of a circle.
|
||||||
|
*
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
configure {
|
configure {
|
||||||
width = 800
|
width = 800
|
||||||
|
|||||||
@@ -42,7 +42,15 @@ More info about the web client:
|
|||||||
## Demos
|
## Demos
|
||||||
### DemoRabbitControl
|
### DemoRabbitControl
|
||||||
|
|
||||||
|
Demonstrates how to use RabbitControl to create a web-based user interface for your program.
|
||||||
|
|
||||||
|
A `settings` object is created using the same syntax used for `orx-gui`, including
|
||||||
|
annotations for different variable types.
|
||||||
|
|
||||||
|
The program then passes these `settings` to the `RabbitControlServer`. A QR-code is displayed
|
||||||
|
to open the web user interface. A clickable URL is also displayed in the console.
|
||||||
|
|
||||||
|
Once the UI is visible in a web browser we can use it to control the OPENRNDR program.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -50,7 +58,10 @@ More info about the web client:
|
|||||||
|
|
||||||
### DemoRabbitControlManualOverlay
|
### DemoRabbitControlManualOverlay
|
||||||
|
|
||||||
|
Demonstrates how the QR-code pointing at the Rabbit Control web-based user interface
|
||||||
|
can be displayed and hidden manually.
|
||||||
|
|
||||||
|
To display the QR-code overlay in this demo, hold down the HOME key in the keyboard.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -58,6 +69,12 @@ More info about the web client:
|
|||||||
|
|
||||||
### DemoRabbitHole
|
### DemoRabbitHole
|
||||||
|
|
||||||
|
Starts the RabbitControlServer with a `Rabbithole` using the key 'orxtest'.
|
||||||
|
|
||||||
|
`Rabbithole` allows you to access your exposed parameters from Internet
|
||||||
|
connected computers that are not in the same network.
|
||||||
|
|
||||||
|
To use it with this example use 'orxtest' as the tunnel-name in https://rabbithole.rabbitcontrol.cc
|
||||||
|
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
@@ -6,7 +6,17 @@ import org.openrndr.math.Vector2
|
|||||||
import org.openrndr.math.Vector3
|
import org.openrndr.math.Vector3
|
||||||
import org.openrndr.math.Vector4
|
import org.openrndr.math.Vector4
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates how to use RabbitControl to create a web-based user interface for your program.
|
||||||
|
*
|
||||||
|
* A `settings` object is created using the same syntax used for `orx-gui`, including
|
||||||
|
* annotations for different variable types.
|
||||||
|
*
|
||||||
|
* The program then passes these `settings` to the `RabbitControlServer`. A QR-code is displayed
|
||||||
|
* to open the web user interface. A clickable URL is also displayed in the console.
|
||||||
|
*
|
||||||
|
* Once the UI is visible in a web browser we can use it to control the OPENRNDR program.
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
configure {
|
configure {
|
||||||
width = 800
|
width = 800
|
||||||
|
|||||||
@@ -4,6 +4,12 @@ import org.openrndr.color.ColorRGBa
|
|||||||
import org.openrndr.extra.parameters.BooleanParameter
|
import org.openrndr.extra.parameters.BooleanParameter
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates how the QR-code pointing at the Rabbit Control web-based user interface
|
||||||
|
* can be displayed and hidden manually.
|
||||||
|
*
|
||||||
|
* To display the QR-code overlay in this demo, hold down the HOME key in the keyboard.
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
configure {
|
configure {
|
||||||
width = 800
|
width = 800
|
||||||
|
|||||||
@@ -6,7 +6,15 @@ import org.openrndr.math.Vector2
|
|||||||
import org.openrndr.math.Vector3
|
import org.openrndr.math.Vector3
|
||||||
import org.openrndr.math.Vector4
|
import org.openrndr.math.Vector4
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts the RabbitControlServer with a `Rabbithole` using the key 'orxtest'.
|
||||||
|
*
|
||||||
|
* `Rabbithole` allows you to access your exposed parameters from Internet
|
||||||
|
* connected computers that are not in the same network.
|
||||||
|
*
|
||||||
|
* To use it with this example use 'orxtest' as the tunnel-name in https://rabbithole.rabbitcontrol.cc
|
||||||
|
*
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
configure {
|
configure {
|
||||||
width = 800
|
width = 800
|
||||||
@@ -14,13 +22,6 @@ fun main() = application {
|
|||||||
}
|
}
|
||||||
|
|
||||||
program {
|
program {
|
||||||
/**
|
|
||||||
* Start RabbitControlServer with a Rabbithole with key 'orxtest'
|
|
||||||
* Please visit https://rabbithole.rabbitcontrol.cc for more information.
|
|
||||||
*
|
|
||||||
* Rabbithole allows you to access your exposed parameter from the internet.
|
|
||||||
* To use it with this example just use 'orxtest' as tunnel-name on the main page.
|
|
||||||
*/
|
|
||||||
val rabbit = RabbitControlServer(false, 10000, 8080, "wss://rabbithole.rabbitcontrol.cc/public/rcpserver/connect?key=orxtest")
|
val rabbit = RabbitControlServer(false, 10000, 8080, "wss://rabbithole.rabbitcontrol.cc/public/rcpserver/connect?key=orxtest")
|
||||||
val font = loadFont("demo-data/fonts/IBMPlexMono-Regular.ttf", 20.0)
|
val font = loadFont("demo-data/fonts/IBMPlexMono-Regular.ttf", 20.0)
|
||||||
val settings = object {
|
val settings = object {
|
||||||
|
|||||||
@@ -105,7 +105,15 @@ Demonstrate decal generation and rendering
|
|||||||
|
|
||||||
### DemoAll
|
### DemoAll
|
||||||
|
|
||||||
|
Demonstrates how to create various types of 3D meshes:
|
||||||
|
box, sphere, dodecahedron, cylinder, plane, cap and resolve.
|
||||||
|
|
||||||
|
Two textures are used: one generative with gradients, and the second
|
||||||
|
one is an image loaded from disk. The horizontal mouse position is used
|
||||||
|
to select which of the two textures to use.
|
||||||
|
|
||||||
|
The meshes are positioned in space using a 2D mesh, and displayed
|
||||||
|
rotating on the X and Y axes at different speeds.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -113,6 +121,18 @@ Demonstrate decal generation and rendering
|
|||||||
|
|
||||||
### DemoBox
|
### DemoBox
|
||||||
|
|
||||||
|
Demonstrates how to create a 3D mesh box by specifying its width, height and depth.
|
||||||
|
|
||||||
|
The `box` is a `VertexBuffer` and contains texture coordinates which can be
|
||||||
|
used to apply a texture to its faces.
|
||||||
|
|
||||||
|
After creating the box, the program creates a texture with a gradient.
|
||||||
|
In it, the red component increases along the x-axis and the green component
|
||||||
|
along the y-axis.
|
||||||
|
|
||||||
|
The scene is rendered with an interactive `Orbital` 3D camera.
|
||||||
|
|
||||||
|
A shade style is used to apply the texture to the box.
|
||||||
|
|
||||||
|
|
||||||

|

|
||||||
@@ -121,7 +141,15 @@ Demonstrate decal generation and rendering
|
|||||||
|
|
||||||
### DemoComplex01
|
### DemoComplex01
|
||||||
|
|
||||||
|
Demonstrates how to use `buildTriangleMesh` to construct composite 3D meshes.
|
||||||
|
|
||||||
|
A DSL allows specifying the color and transformations of each mesh, in this case,
|
||||||
|
of a sphere and a box.
|
||||||
|
|
||||||
|
An interactive 3D Orbital camera is defined, specifying the location of its `eye` and
|
||||||
|
`lookAt` properties.
|
||||||
|
|
||||||
|
A minimal shade style is used to simulate a uni-directional light pointing along the view Z axis.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -129,7 +157,7 @@ Demonstrate decal generation and rendering
|
|||||||
|
|
||||||
### DemoComplex02
|
### DemoComplex02
|
||||||
|
|
||||||
|
Demonstrates the creation of a 3D mesh composed of two hemispheres, a cylinder and 12 legs.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -137,7 +165,14 @@ Demonstrate decal generation and rendering
|
|||||||
|
|
||||||
### DemoComplex03
|
### DemoComplex03
|
||||||
|
|
||||||
|
Demonstrates the creation of a 3D mesh composed of two hemispheres, a cylinder and 12 legs.
|
||||||
|
Additionally, the body of the shape features 5 ridges on the sides
|
||||||
|
of the cylinder.
|
||||||
|
|
||||||
|
The code reveals DSL keywords under `buildTriangleMesh`
|
||||||
|
affecting transformation matrices, for instance `isolated`, `translate` and `rotate`,
|
||||||
|
and mesh generating keywords like
|
||||||
|
`hemisphere`, `taperedCylinder` and `cylinder`.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -145,7 +180,9 @@ Demonstrate decal generation and rendering
|
|||||||
|
|
||||||
### DemoComplex04
|
### DemoComplex04
|
||||||
|
|
||||||
|
Demonstrates the use of `buildTriangleMesh` to create
|
||||||
|
a composite 3D mesh and introduces a new mesh generating keyword:
|
||||||
|
`cap`.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -153,6 +190,9 @@ Demonstrate decal generation and rendering
|
|||||||
|
|
||||||
### DemoComplex05
|
### DemoComplex05
|
||||||
|
|
||||||
|
Demonstrates how to create a 3D grid of extruded shapes
|
||||||
|
(short cylinders), then applies three 3D twists to the
|
||||||
|
composition to deform it.
|
||||||
|
|
||||||
|
|
||||||

|

|
||||||
@@ -161,8 +201,11 @@ Demonstrate decal generation and rendering
|
|||||||
|
|
||||||
### DemoComplex06
|
### DemoComplex06
|
||||||
|
|
||||||
Generates a grid of grids of boxes.
|
Generates a grid of grids of 3D boxes using `buildTriangleMesh` and
|
||||||
Interactive orbital camera.
|
renders them using an interactive orbital camera.
|
||||||
|
|
||||||
|
The cubes ar colorized using a shade style that sets colors based
|
||||||
|
on vertex positions in space, converting XYZ coordinates into RGB colors.
|
||||||
|
|
||||||
|
|
||||||

|

|
||||||
@@ -270,7 +313,13 @@ for a radial-symmetry effect.
|
|||||||
|
|
||||||
### tangents/DemoTangents01
|
### tangents/DemoTangents01
|
||||||
|
|
||||||
|
Tangent and bitangent vectors are used in shader programs for tangent space normal mapping / lighting
|
||||||
|
and certain forms of displacement mapping.
|
||||||
|
|
||||||
|
This demo shows:
|
||||||
|
- how to create a triangulated `MeshData`.
|
||||||
|
- how to estimate the tangents of this MeshData.
|
||||||
|
- How to use the tangent and bitangent attributes in GLSL code.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,17 @@ import org.openrndr.math.Vector2
|
|||||||
import org.openrndr.math.Vector3
|
import org.openrndr.math.Vector3
|
||||||
import org.openrndr.shape.Rectangle
|
import org.openrndr.shape.Rectangle
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates how to create various types of 3D meshes:
|
||||||
|
* box, sphere, dodecahedron, cylinder, plane, cap and resolve.
|
||||||
|
*
|
||||||
|
* Two textures are used: one generative with gradients, and the second
|
||||||
|
* one is an image loaded from disk. The horizontal mouse position is used
|
||||||
|
* to select which of the two textures to use.
|
||||||
|
*
|
||||||
|
* The meshes are positioned in space using a 2D mesh, and displayed
|
||||||
|
* rotating on the X and Y axes at different speeds.
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
configure {
|
configure {
|
||||||
width = 720
|
width = 720
|
||||||
|
|||||||
@@ -9,6 +9,21 @@ import org.openrndr.extra.camera.Orbital
|
|||||||
import org.openrndr.extra.meshgenerators.boxMesh
|
import org.openrndr.extra.meshgenerators.boxMesh
|
||||||
import org.openrndr.math.Vector3
|
import org.openrndr.math.Vector3
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates how to create a 3D mesh box by specifying its width, height and depth.
|
||||||
|
*
|
||||||
|
* The `box` is a `VertexBuffer` and contains texture coordinates which can be
|
||||||
|
* used to apply a texture to its faces.
|
||||||
|
*
|
||||||
|
* After creating the box, the program creates a texture with a gradient.
|
||||||
|
* In it, the red component increases along the x-axis and the green component
|
||||||
|
* along the y-axis.
|
||||||
|
*
|
||||||
|
* The scene is rendered with an interactive `Orbital` 3D camera.
|
||||||
|
*
|
||||||
|
* A shade style is used to apply the texture to the box.
|
||||||
|
*
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
configure {
|
configure {
|
||||||
width = 720
|
width = 720
|
||||||
|
|||||||
@@ -9,6 +9,17 @@ import org.openrndr.extra.meshgenerators.buildTriangleMesh
|
|||||||
import org.openrndr.extra.meshgenerators.sphere
|
import org.openrndr.extra.meshgenerators.sphere
|
||||||
import org.openrndr.math.Vector3
|
import org.openrndr.math.Vector3
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates how to use `buildTriangleMesh` to construct composite 3D meshes.
|
||||||
|
*
|
||||||
|
* A DSL allows specifying the color and transformations of each mesh, in this case,
|
||||||
|
* of a sphere and a box.
|
||||||
|
*
|
||||||
|
* An interactive 3D Orbital camera is defined, specifying the location of its `eye` and
|
||||||
|
* `lookAt` properties.
|
||||||
|
*
|
||||||
|
* A minimal shade style is used to simulate a uni-directional light pointing along the view Z axis.
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
configure {
|
configure {
|
||||||
width = 720
|
width = 720
|
||||||
|
|||||||
@@ -8,6 +8,9 @@ import org.openrndr.extra.meshgenerators.cylinder
|
|||||||
import org.openrndr.extra.meshgenerators.hemisphere
|
import org.openrndr.extra.meshgenerators.hemisphere
|
||||||
import org.openrndr.math.Vector3
|
import org.openrndr.math.Vector3
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates the creation of a 3D mesh composed of two hemispheres, a cylinder and 12 legs.
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
configure {
|
configure {
|
||||||
width = 720
|
width = 720
|
||||||
|
|||||||
@@ -6,6 +6,16 @@ import org.openrndr.extra.camera.Orbital
|
|||||||
import org.openrndr.extra.meshgenerators.*
|
import org.openrndr.extra.meshgenerators.*
|
||||||
import org.openrndr.math.Vector3
|
import org.openrndr.math.Vector3
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates the creation of a 3D mesh composed of two hemispheres, a cylinder and 12 legs.
|
||||||
|
* Additionally, the body of the shape features 5 ridges on the sides
|
||||||
|
* of the cylinder.
|
||||||
|
*
|
||||||
|
* The code reveals DSL keywords under `buildTriangleMesh`
|
||||||
|
* affecting transformation matrices, for instance `isolated`, `translate` and `rotate`,
|
||||||
|
* and mesh generating keywords like
|
||||||
|
* `hemisphere`, `taperedCylinder` and `cylinder`.
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
configure {
|
configure {
|
||||||
width = 720
|
width = 720
|
||||||
|
|||||||
@@ -7,6 +7,11 @@ import org.openrndr.extra.meshgenerators.*
|
|||||||
import org.openrndr.math.Vector2
|
import org.openrndr.math.Vector2
|
||||||
import org.openrndr.math.Vector3
|
import org.openrndr.math.Vector3
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates the use of `buildTriangleMesh` to create
|
||||||
|
* a composite 3D mesh and introduces a new mesh generating keyword:
|
||||||
|
* `cap`.
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
configure {
|
configure {
|
||||||
width = 720
|
width = 720
|
||||||
|
|||||||
@@ -11,6 +11,12 @@ import org.openrndr.extra.meshgenerators.twist
|
|||||||
import org.openrndr.math.Vector3
|
import org.openrndr.math.Vector3
|
||||||
import org.openrndr.shape.Circle
|
import org.openrndr.shape.Circle
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates how to create a 3D grid of extruded shapes
|
||||||
|
* (short cylinders), then applies three 3D twists to the
|
||||||
|
* composition to deform it.
|
||||||
|
*
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
configure {
|
configure {
|
||||||
width = 720
|
width = 720
|
||||||
|
|||||||
@@ -9,8 +9,11 @@ import org.openrndr.extra.noise.simplex
|
|||||||
import org.openrndr.math.Vector3
|
import org.openrndr.math.Vector3
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a grid of grids of boxes.
|
* Generates a grid of grids of 3D boxes using `buildTriangleMesh` and
|
||||||
* Interactive orbital camera.
|
* renders them using an interactive orbital camera.
|
||||||
|
*
|
||||||
|
* The cubes ar colorized using a shade style that sets colors based
|
||||||
|
* on vertex positions in space, converting XYZ coordinates into RGB colors.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
|
|||||||
@@ -10,6 +10,15 @@ import org.openrndr.extra.objloader.loadOBJMeshData
|
|||||||
import org.openrndr.math.Vector3
|
import org.openrndr.math.Vector3
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tangent and bitangent vectors are used in shader programs for tangent space normal mapping / lighting
|
||||||
|
* and certain forms of displacement mapping.
|
||||||
|
*
|
||||||
|
* This demo shows:
|
||||||
|
* - how to create a triangulated `MeshData`.
|
||||||
|
* - how to estimate the tangents of this MeshData.
|
||||||
|
* - How to use the tangent and bitangent attributes in GLSL code.
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
configure {
|
configure {
|
||||||
width = 720
|
width = 720
|
||||||
@@ -29,12 +38,11 @@ fun main() = application {
|
|||||||
fragmentTransform = """
|
fragmentTransform = """
|
||||||
vec3 viewTangent = (u_viewNormalMatrix * u_modelNormalMatrix * vec4(va_tangent, 0.0)).xyz;
|
vec3 viewTangent = (u_viewNormalMatrix * u_modelNormalMatrix * vec4(va_tangent, 0.0)).xyz;
|
||||||
vec3 viewBitangent = (u_viewNormalMatrix * u_modelNormalMatrix * vec4(va_bitangent, 0.0)).xyz;
|
vec3 viewBitangent = (u_viewNormalMatrix * u_modelNormalMatrix * vec4(va_bitangent, 0.0)).xyz;
|
||||||
float c = cos(100.0*dot(v_worldPosition, va_normal)) * 0.5 + 0.5;
|
float c = cos(100.0 * dot(v_worldPosition, va_normal)) * 0.5 + 0.5;
|
||||||
|
|
||||||
//x_fill.rgb = normalize(viewTangent)*0.5+0.5;
|
//x_fill.rgb = normalize(viewTangent) * 0.5 + 0.5;
|
||||||
x_fill.rgb = vec3(c);
|
x_fill.rgb = vec3(c);
|
||||||
""".trimIndent()
|
""".trimIndent()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
drawer.vertexBuffer(objVB, DrawPrimitive.TRIANGLES)
|
drawer.vertexBuffer(objVB, DrawPrimitive.TRIANGLES)
|
||||||
|
|||||||
@@ -465,6 +465,31 @@ to round contours with linear segments.
|
|||||||
|
|
||||||
[source code](src/jvmDemo/kotlin/hobbycurve/DemoHobbyCurve03.kt)
|
[source code](src/jvmDemo/kotlin/hobbycurve/DemoHobbyCurve03.kt)
|
||||||
|
|
||||||
|
### hobbycurve/DemoHobbyCurve04
|
||||||
|
|
||||||
|
Demonstrates the use of the `tensions` argument when creating a Hobby curve.
|
||||||
|
|
||||||
|
The program starts by creating a random set of scattered points with enough separation between them.
|
||||||
|
The points are sorted using `hilbertOrder` to minimize the travel distance when visiting all the points.
|
||||||
|
Finally, we draw a set of 40 hobby translucent curves using those same points but with varying tensions.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
[source code](src/jvmDemo/kotlin/hobbycurve/DemoHobbyCurve04.kt)
|
||||||
|
|
||||||
|
### hobbycurve/DemoHobbyCurve05
|
||||||
|
|
||||||
|
Demonstrates the creation of a 40 hobby curves with 10 points each.
|
||||||
|
The control points in all hobby curves are almost identical, varying only
|
||||||
|
due to a slight increase in one of the arguments of a simplex noise call.
|
||||||
|
|
||||||
|
The program shows that minor displacements in control points can have
|
||||||
|
a large impact in the resulting curve.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
[source code](src/jvmDemo/kotlin/hobbycurve/DemoHobbyCurve05.kt)
|
||||||
|
|
||||||
### hobbycurve/DemoHobbyCurve3D01
|
### hobbycurve/DemoHobbyCurve3D01
|
||||||
|
|
||||||
Demonstrates how to use the 3D implementation of the `hobbyCurve` method, to draw a smooth curve passing
|
Demonstrates how to use the 3D implementation of the `hobbyCurve` method, to draw a smooth curve passing
|
||||||
@@ -678,6 +703,22 @@ Demonstrate rectangle-rectangle intersection
|
|||||||
|
|
||||||
[source code](src/jvmDemo/kotlin/primitives/DemoRectangleIntersection01.kt)
|
[source code](src/jvmDemo/kotlin/primitives/DemoRectangleIntersection01.kt)
|
||||||
|
|
||||||
|
### primitives/DemoRectangleIrregularGrid02
|
||||||
|
|
||||||
|
Demonstrates how to use `Rectangle.irregularGrid()` to create a grid with varying column widths
|
||||||
|
and row heights. The widths and heights are specified as a list of 13 `Double` values, each
|
||||||
|
picked randomly between the values 1.0 and 4.0. This produces two types of columns and two
|
||||||
|
types of rows only: wide ones and narrow ones.
|
||||||
|
|
||||||
|
The program also demonstrates how to query a `row()` and a `column()` from a `RectangleGrid` instance,
|
||||||
|
both of which return a `List<Rectangle>`. Both `Rectangle` lists are rendered with translucent
|
||||||
|
colors, which makes the intersection of the column and the row slightly brighter.
|
||||||
|
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
[source code](src/jvmDemo/kotlin/primitives/DemoRectangleIrregularGrid02.kt)
|
||||||
|
|
||||||
### primitives/DemoRectangleIrregularGrid
|
### primitives/DemoRectangleIrregularGrid
|
||||||
|
|
||||||
|
|
||||||
@@ -749,6 +790,21 @@ This serves as a demonstration of positioning and rendering shapes in a structur
|
|||||||
|
|
||||||
[source code](src/jvmDemo/kotlin/primitives/DemoTear01.kt)
|
[source code](src/jvmDemo/kotlin/primitives/DemoTear01.kt)
|
||||||
|
|
||||||
|
### primitives/DemoTear02
|
||||||
|
|
||||||
|
Demonstrates the use of `Tear()` to create drop-like shapes out of a Vector2 point and a Circle.
|
||||||
|
|
||||||
|
The tear locations are calculated using the `Rectangle.scatter()` function. Locations near the
|
||||||
|
center of the window are filtered out.
|
||||||
|
|
||||||
|
The radii of each tear is randomly chosen between three values. The orientation of each tear
|
||||||
|
is calculated by getting the normalized difference between the tear and the center of the window,
|
||||||
|
making them look as being emitted at the center of the window.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
[source code](src/jvmDemo/kotlin/primitives/DemoTear02.kt)
|
||||||
|
|
||||||
### rectify/DemoRectifiedContour01
|
### rectify/DemoRectifiedContour01
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
38
orx-shapes/src/jvmDemo/kotlin/hobbycurve/DemoHobbyCurve04.kt
Normal file
38
orx-shapes/src/jvmDemo/kotlin/hobbycurve/DemoHobbyCurve04.kt
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package hobbycurve
|
||||||
|
|
||||||
|
import org.openrndr.application
|
||||||
|
import org.openrndr.color.ColorRGBa
|
||||||
|
import org.openrndr.extra.noise.scatter
|
||||||
|
import org.openrndr.extra.shapes.hobbycurve.hobbyCurve
|
||||||
|
import org.openrndr.extra.shapes.ordering.hilbertOrder
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates the use of the `tensions` argument when creating a Hobby curve.
|
||||||
|
*
|
||||||
|
* The program starts by creating a random set of scattered points with enough separation between them.
|
||||||
|
* The points are sorted using `hilbertOrder` to minimize the travel distance when visiting all the points.
|
||||||
|
* Finally, we draw a set of 40 hobby translucent curves using those same points but with varying tensions.
|
||||||
|
*/
|
||||||
|
fun main() = application {
|
||||||
|
configure {
|
||||||
|
width = 720
|
||||||
|
height = 720
|
||||||
|
}
|
||||||
|
program {
|
||||||
|
extend {
|
||||||
|
for (i in -20..20) {
|
||||||
|
val t = i / 10.0
|
||||||
|
val points = drawer.bounds.offsetEdges(-50.0)
|
||||||
|
.scatter(25.0, random = Random(0))
|
||||||
|
.hilbertOrder()
|
||||||
|
|
||||||
|
drawer.stroke = ColorRGBa.WHITE.opacify(0.5)
|
||||||
|
drawer.fill = null
|
||||||
|
drawer.contour(hobbyCurve(points, closed = false, tensions = { i, inAngle, outAngle ->
|
||||||
|
Pair(t, t)
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
38
orx-shapes/src/jvmDemo/kotlin/hobbycurve/DemoHobbyCurve05.kt
Normal file
38
orx-shapes/src/jvmDemo/kotlin/hobbycurve/DemoHobbyCurve05.kt
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package hobbycurve
|
||||||
|
|
||||||
|
import org.openrndr.application
|
||||||
|
import org.openrndr.color.ColorRGBa
|
||||||
|
import org.openrndr.extra.color.presets.WHITE_SMOKE
|
||||||
|
import org.openrndr.extra.noise.simplex
|
||||||
|
import org.openrndr.extra.noise.uniform
|
||||||
|
import org.openrndr.extra.shapes.hobbycurve.hobbyCurve
|
||||||
|
import org.openrndr.extra.shapes.ordering.hilbertOrder
|
||||||
|
import org.openrndr.math.Vector2
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates the creation of a 40 hobby curves with 10 points each.
|
||||||
|
* The control points in all hobby curves are almost identical, varying only
|
||||||
|
* due to a slight increase in one of the arguments of a simplex noise call.
|
||||||
|
*
|
||||||
|
* The program shows that minor displacements in control points can have
|
||||||
|
* a large impact in the resulting curve.
|
||||||
|
*/
|
||||||
|
fun main() = application {
|
||||||
|
program {
|
||||||
|
val seed = 68040
|
||||||
|
val curves = List(40) { n ->
|
||||||
|
hobbyCurve(List(10) {
|
||||||
|
Vector2(
|
||||||
|
simplex(seed, it * 13.3, n * 0.001) * 300.0 + 320.0,
|
||||||
|
simplex(seed / 2, it * 77.4, n * 0.001) * 300.0 + 240.0
|
||||||
|
)
|
||||||
|
}.hilbertOrder(), true)
|
||||||
|
}
|
||||||
|
extend {
|
||||||
|
drawer.clear(ColorRGBa.WHITE_SMOKE)
|
||||||
|
drawer.fill = null
|
||||||
|
drawer.stroke = ColorRGBa.BLACK.opacify(0.3)
|
||||||
|
drawer.contours(curves)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package primitives
|
||||||
|
|
||||||
|
import org.openrndr.application
|
||||||
|
import org.openrndr.color.ColorRGBa
|
||||||
|
import org.openrndr.extra.color.presets.CORAL
|
||||||
|
import org.openrndr.extra.shapes.primitives.column
|
||||||
|
import org.openrndr.extra.shapes.primitives.irregularGrid
|
||||||
|
import org.openrndr.extra.shapes.primitives.row
|
||||||
|
import kotlin.random.Random
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates how to use `Rectangle.irregularGrid()` to create a grid with varying column widths
|
||||||
|
* and row heights. The widths and heights are specified as a list of 13 `Double` values, each
|
||||||
|
* picked randomly between the values 1.0 and 4.0. This produces two types of columns and two
|
||||||
|
* types of rows only: wide ones and narrow ones.
|
||||||
|
*
|
||||||
|
* The program also demonstrates how to query a `row()` and a `column()` from a `RectangleGrid` instance,
|
||||||
|
* both of which return a `List<Rectangle>`. Both `Rectangle` lists are rendered with translucent
|
||||||
|
* colors, which makes the intersection of the column and the row slightly brighter.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
fun main() = application {
|
||||||
|
configure {
|
||||||
|
width = 720
|
||||||
|
height = 720
|
||||||
|
}
|
||||||
|
program {
|
||||||
|
extend {
|
||||||
|
val r = Random(100)
|
||||||
|
val grid = drawer.bounds.irregularGrid(
|
||||||
|
List(13) { listOf(1.0, 4.0).random(r) },
|
||||||
|
List(13) { listOf(1.0, 4.0).random(r) }
|
||||||
|
)
|
||||||
|
|
||||||
|
drawer.fill = null
|
||||||
|
drawer.stroke = ColorRGBa.WHITE
|
||||||
|
drawer.rectangles(grid.flatten())
|
||||||
|
|
||||||
|
drawer.stroke = ColorRGBa.BLACK
|
||||||
|
drawer.fill = ColorRGBa.PINK.opacify(0.5)
|
||||||
|
drawer.rectangles(grid.column(2))
|
||||||
|
|
||||||
|
drawer.fill = ColorRGBa.CORAL.opacify(0.5)
|
||||||
|
drawer.rectangles(grid.row(6))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
42
orx-shapes/src/jvmDemo/kotlin/primitives/DemoTear02.kt
Normal file
42
orx-shapes/src/jvmDemo/kotlin/primitives/DemoTear02.kt
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package primitives
|
||||||
|
|
||||||
|
import org.openrndr.application
|
||||||
|
import org.openrndr.color.ColorRGBa
|
||||||
|
import org.openrndr.extra.noise.scatter
|
||||||
|
import org.openrndr.extra.shapes.primitives.Tear
|
||||||
|
import org.openrndr.shape.Circle
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates the use of `Tear()` to create drop-like shapes out of a Vector2 point and a Circle.
|
||||||
|
*
|
||||||
|
* The tear locations are calculated using the `Rectangle.scatter()` function. Locations near the
|
||||||
|
* center of the window are filtered out.
|
||||||
|
*
|
||||||
|
* The radii of each tear is randomly chosen between three values. The orientation of each tear
|
||||||
|
* is calculated by getting the normalized difference between the tear and the center of the window,
|
||||||
|
* making them look as being emitted at the center of the window.
|
||||||
|
*/
|
||||||
|
fun main() = application {
|
||||||
|
configure {
|
||||||
|
width = 720
|
||||||
|
height = 720
|
||||||
|
}
|
||||||
|
program {
|
||||||
|
val points = drawer.bounds.scatter(40.0, distanceToEdge = 80.0).filter {
|
||||||
|
it.distanceTo(drawer.bounds.center) > 80.0
|
||||||
|
}
|
||||||
|
|
||||||
|
val tears = points.map {
|
||||||
|
val radius = listOf(5.0, 10.0, 20.0).random()
|
||||||
|
val offset = (it - drawer.bounds.center).normalized * radius
|
||||||
|
Tear(it - offset, Circle(it + offset, radius))
|
||||||
|
}
|
||||||
|
|
||||||
|
extend {
|
||||||
|
drawer.clear(ColorRGBa.WHITE)
|
||||||
|
drawer.fill = ColorRGBa.PINK
|
||||||
|
drawer.stroke = ColorRGBa.BLACK
|
||||||
|
drawer.contours(tears.map { it.contour })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -37,6 +37,11 @@ Note that drawing inside the `repeat` action has no effect. Have a look at the d
|
|||||||
## Demos
|
## Demos
|
||||||
### DemoRepeat01
|
### DemoRepeat01
|
||||||
|
|
||||||
|
A simple demonstration on using the `repeat` method to execute a function
|
||||||
|
at regular intervals.
|
||||||
|
|
||||||
|
Note that drawing inside the repeat action has no effect.
|
||||||
|
See DemoRepeat02.kt to learn how to trigger drawing.
|
||||||
|
|
||||||
|
|
||||||

|

|
||||||
@@ -45,14 +50,29 @@ Note that drawing inside the `repeat` action has no effect. Have a look at the d
|
|||||||
|
|
||||||
### DemoRepeat02
|
### DemoRepeat02
|
||||||
|
|
||||||
This demonstrates how to combine `repeat {}` with a postponed event to trigger drawing
|
This demonstrates how to combine `repeat {}` with a postponed event to trigger drawing.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
[source code](src/demo/kotlin/DemoRepeat02.kt)
|
[source code](src/demo/kotlin/DemoRepeat02.kt)
|
||||||
|
|
||||||
|
### DemoRepeat03
|
||||||
|
|
||||||
|
Shows how a `repeat` block can update a variable used
|
||||||
|
for rendering. In this demo, the `opacity` variable is
|
||||||
|
reduced on every animation frame, and increased to 1.0
|
||||||
|
every 2 seconds, creating a pulsating animation effect.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
[source code](src/demo/kotlin/DemoRepeat03.kt)
|
||||||
|
|
||||||
### DemoTimeOut01
|
### DemoTimeOut01
|
||||||
|
|
||||||
|
Demonstrates the `timeOut` function.
|
||||||
|
|
||||||
|
It is similar to the `repeat` function,
|
||||||
|
but it runs only once after the specified delay in seconds.
|
||||||
|
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
@@ -1,6 +1,14 @@
|
|||||||
import org.openrndr.application
|
import org.openrndr.application
|
||||||
import org.openrndr.extra.timer.repeat
|
import org.openrndr.extra.timer.repeat
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A simple demonstration on using the `repeat` method to execute a function
|
||||||
|
* at regular intervals.
|
||||||
|
*
|
||||||
|
* Note that drawing inside the repeat action has no effect.
|
||||||
|
* See DemoRepeat02.kt to learn how to trigger drawing.
|
||||||
|
*
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
program {
|
program {
|
||||||
repeat(2.0) {
|
repeat(2.0) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import org.openrndr.events.Event
|
|||||||
import org.openrndr.extra.timer.repeat
|
import org.openrndr.extra.timer.repeat
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This demonstrates how to combine `repeat {}` with a postponed event to trigger drawing
|
* This demonstrates how to combine `repeat {}` with a postponed event to trigger drawing.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
|
|||||||
25
orx-timer/src/demo/kotlin/DemoRepeat03.kt
Normal file
25
orx-timer/src/demo/kotlin/DemoRepeat03.kt
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
import org.openrndr.application
|
||||||
|
import org.openrndr.color.ColorRGBa
|
||||||
|
import org.openrndr.extra.timer.repeat
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows how a `repeat` block can update a variable used
|
||||||
|
* for rendering. In this demo, the `opacity` variable is
|
||||||
|
* reduced on every animation frame, and increased to 1.0
|
||||||
|
* every 2 seconds, creating a pulsating animation effect.
|
||||||
|
*/
|
||||||
|
fun main() = application {
|
||||||
|
program {
|
||||||
|
var opacity = 0.0
|
||||||
|
repeat(2.0) {
|
||||||
|
opacity = 1.0
|
||||||
|
}
|
||||||
|
extend {
|
||||||
|
drawer.clear(ColorRGBa.PINK)
|
||||||
|
drawer.stroke = ColorRGBa.BLACK.opacify(opacity)
|
||||||
|
drawer.fill = ColorRGBa.WHITE.opacify(opacity)
|
||||||
|
drawer.circle(width / 2.0, height / 2.0, 200.0)
|
||||||
|
opacity *= 0.9
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,13 @@
|
|||||||
import org.openrndr.application
|
import org.openrndr.application
|
||||||
import org.openrndr.extra.timer.timeOut
|
import org.openrndr.extra.timer.timeOut
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demonstrates the `timeOut` function.
|
||||||
|
*
|
||||||
|
* It is similar to the `repeat` function,
|
||||||
|
* but it runs only once after the specified delay in seconds.
|
||||||
|
*
|
||||||
|
*/
|
||||||
fun main() = application {
|
fun main() = application {
|
||||||
program {
|
program {
|
||||||
timeOut(2.0) {
|
timeOut(2.0) {
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ The language also holds some tools to manage the position and orientation of the
|
|||||||
## Demos
|
## Demos
|
||||||
### DemoTurtle01
|
### DemoTurtle01
|
||||||
|
|
||||||
/*
|
|
||||||
Drawing a square using the turtle interface.
|
Drawing a square using the turtle interface.
|
||||||
|
|
||||||

|

|
||||||
@@ -44,7 +43,6 @@ Drawing a square using the turtle interface.
|
|||||||
|
|
||||||
### DemoTurtle02
|
### DemoTurtle02
|
||||||
|
|
||||||
/*
|
|
||||||
A simple random walk made using the turtle interface.
|
A simple random walk made using the turtle interface.
|
||||||
|
|
||||||

|

|
||||||
@@ -53,7 +51,6 @@ A simple random walk made using the turtle interface.
|
|||||||
|
|
||||||
### DemoTurtle03
|
### DemoTurtle03
|
||||||
|
|
||||||
/*
|
|
||||||
Drawing shape contours aligned to the turtle's orientation.
|
Drawing shape contours aligned to the turtle's orientation.
|
||||||
|
|
||||||

|

|
||||||
|
|||||||
Reference in New Issue
Block a user