[orx-noise] Add hash functions

This commit is contained in:
Edwin Jakobs
2024-10-20 14:14:50 +02:00
parent 6e1e161726
commit fba1e5b61a
23 changed files with 473 additions and 63 deletions

View File

@@ -186,11 +186,16 @@ class ShapeNode(var shape: Shape) : CompositionNode() {
} }
} }
/** /**
* apply transforms of all ancestor nodes and return a new detached shape node with identity transform and transformed Shape * apply transforms of all ancestor nodes and return a new detached shape node with identity transform and transformed Shape
* @param composition use viewport transform
*/ */
fun flatten(): ShapeNode { fun flatten(composition: Composition? = null): ShapeNode {
return ShapeNode(shape.transform(transform(this))).also {
val viewport = composition?.calculateViewportTransform() ?: Matrix44.IDENTITY
return ShapeNode(shape.transform(viewport * transform(this))).also {
it.id = id it.id = id
it.parent = parent it.parent = parent
it.style = effectiveStyle it.style = effectiveStyle
@@ -293,10 +298,10 @@ data class CompositionDimensions(val x: Length, val y: Length, val width: Length
// but otherwise equality checks will never succeed // but otherwise equality checks will never succeed
override fun equals(other: Any?): Boolean { override fun equals(other: Any?): Boolean {
return other is CompositionDimensions return other is CompositionDimensions
&& x.value == other.x.value && x.value == other.x.value
&& y.value == other.y.value && y.value == other.y.value
&& width.value == other.width.value && width.value == other.width.value
&& height.value == other.height.value && height.value == other.height.value
} }
override fun hashCode(): Int { override fun hashCode(): Int {

View File

@@ -1,7 +1,7 @@
import org.openrndr.application import org.openrndr.application
import org.openrndr.draw.loadFont import org.openrndr.draw.loadFont
import org.openrndr.extra.envelopes.ADSRTracker import org.openrndr.extra.envelopes.ADSRTracker
import org.openrndr.extra.noise.uniform import org.openrndr.extra.noise.shapes.uniform
import org.openrndr.shape.Rectangle import org.openrndr.shape.Rectangle
fun main() { fun main() {
@@ -15,13 +15,13 @@ fun main() {
keyboard.keyDown.listen { keyboard.keyDown.listen {
if (it.name == "t") { if (it.name == "t") {
val center = drawer.bounds.uniform(distanceToEdge = 30.0) val center = drawer.bounds.offsetEdges(-30.0).uniform()
tracker.triggerOn(0) { time, value, position -> tracker.triggerOn(0) { time, value, position ->
drawer.circle(center, value * 100.0) drawer.circle(center, value * 100.0)
} }
} }
if (it.name == "r") { if (it.name == "r") {
val center = drawer.bounds.uniform(distanceToEdge = 30.0) val center = drawer.bounds.offsetEdges(-30.0).uniform()
tracker.triggerOn(1) { time, value, position -> tracker.triggerOn(1) { time, value, position ->
val r = Rectangle.fromCenter(center, width = value * 100.0, height = value * 100.0) val r = Rectangle.fromCenter(center, width = value * 100.0, height = value * 100.0)
drawer.rectangle(r) drawer.rectangle(r)

View File

@@ -1,7 +1,7 @@
package typed package typed
import org.openrndr.extra.expressions.typed.compileFunction1OrNull import org.openrndr.extra.expressions.typed.compileFunction1OrNull
import org.openrndr.extra.noise.uniform import org.openrndr.extra.noise.shapes.uniform
import org.openrndr.math.Vector2 import org.openrndr.math.Vector2
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals

View File

@@ -1,6 +1,6 @@
import org.openrndr.application import org.openrndr.application
import org.openrndr.extra.hashgrid.filter import org.openrndr.extra.hashgrid.filter
import org.openrndr.extra.noise.uniform import org.openrndr.extra.noise.shapes.uniform
import kotlin.random.Random import kotlin.random.Random
fun main() { fun main() {

View File

@@ -1,7 +1,7 @@
import org.openrndr.application import org.openrndr.application
import org.openrndr.color.ColorRGBa import org.openrndr.color.ColorRGBa
import org.openrndr.extra.hashgrid.HashGrid import org.openrndr.extra.hashgrid.HashGrid
import org.openrndr.extra.noise.uniform import org.openrndr.extra.noise.shapes.uniform
import kotlin.random.Random import kotlin.random.Random
fun main() { fun main() {

View File

@@ -0,0 +1,72 @@
package org.openrndr.extra.mesh.generators
import org.openrndr.extra.mesh.*
import org.openrndr.math.Vector2
import org.openrndr.math.Vector3
class MeshBuilder {
val vertexData = MutableVertexData()
val polygons = mutableListOf<IndexedPolygon>()
val mesh = MutableMeshData(vertexData, polygons)
}
fun box(): MeshData {
val positions = listOf(
Vector3(-0.5, -0.5, -0.5),
Vector3(0.5, -0.5, -0.5),
Vector3(-0.5, 0.5, -0.5),
Vector3(0.5, 0.5, -0.5),
Vector3(-0.5, -0.5, 0.5),
Vector3(0.5, -0.5, 0.5),
Vector3(-0.5, 0.5, 0.5),
Vector3(0.5, 0.5, 0.5),
)
val textureCoords = listOf(
Vector2(0.0, 0.0),
Vector2(1.0, 0.0),
Vector2(0.0, 1.0),
Vector2(1.0, 1.0),
)
val normals = listOf(
Vector3(-1.0, 0.0, 0.0),
Vector3(1.0, 0.0, 0.0),
Vector3(0.0, -1.0, 0.0),
Vector3(0.0, 1.0, 0.0),
Vector3(0.0, 0.0, -1.0),
Vector3(0.0, 0.0, 1.0)
)
val polygons = listOf(
// -x
IndexedPolygon(
positions = listOf(0, 2, 4, 6),
textureCoords = listOf(0, 1, 3, 2),
colors = emptyList(),
normals = listOf(0, 0, 0, 0),
tangents = listOf(5, 5, 5, 5),
bitangents = listOf(3, 3, 3, 3)
),
// +x
IndexedPolygon(
positions = listOf(1, 3, 5, 7),
textureCoords = listOf(0, 1, 3, 2),
colors = emptyList(),
normals = listOf(1, 1, 1, 1),
tangents = listOf(4, 4, 4, 4),
bitangents = listOf(3, 3, 3, 3)
)
)
return MeshData(
VertexData(
positions = positions,
textureCoords = textureCoords,
normals = normals,
tangents = normals,
bitangents = normals
), polygons
)
}

View File

@@ -13,6 +13,7 @@ import java.io.File
/** /**
* Demonstrate decal generator as an object slicer * Demonstrate decal generator as an object slicer
* @see <img src="https://raw.githubusercontent.com/openrndr/orx/media/orx-mesh-generators/images/decal-DemoDecal01Kt.png">
*/ */
fun main() { fun main() {
application { application {

View File

@@ -15,6 +15,7 @@ import kotlin.math.PI
/** /**
* Demonstrate decal generation and rendering * Demonstrate decal generation and rendering
* @see <img src="https://raw.githubusercontent.com/openrndr/orx/media/orx-mesh-generators/images/decal-DemoDecal02Kt.png">
*/ */
fun main() { fun main() {
application { application {

View File

@@ -0,0 +1,39 @@
package tangents
import org.openrndr.application
import org.openrndr.draw.DrawPrimitive
import org.openrndr.draw.shadeStyle
import org.openrndr.extra.camera.Orbital
import org.openrndr.extra.mesh.toVertexBuffer
import org.openrndr.extra.meshgenerators.tangents.estimateTangents
import org.openrndr.extra.objloader.loadOBJMeshData
import org.openrndr.math.Vector3
import java.io.File
fun main() = application {
program {
val obj = loadOBJMeshData(File("demo-data/obj-models/suzanne/Suzanne.obj")).toMeshData().triangulate()
val tangentObj = obj.estimateTangents()
val objVB = tangentObj.toVertexBuffer()
extend(Orbital()) {
eye = Vector3(0.0, 0.0, 2.0)
}
extend {
drawer.shadeStyle = shadeStyle {
fragmentTransform = """
vec3 viewTangent = (u_viewNormalMatrix * u_modelNormalMatrix * vec4(va_tangent, 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;
//x_fill.rgb = normalize(viewTangent)*0.5+0.5;
x_fill.rgb = vec3(c);
""".trimIndent()
}
drawer.vertexBuffer(objVB, DrawPrimitive.TRIANGLES)
}
}
}

View File

@@ -10,6 +10,7 @@ kotlin {
api(libs.openrndr.math) api(libs.openrndr.math)
api(libs.openrndr.shape) api(libs.openrndr.shape)
api(project(":orx-mesh")) api(project(":orx-mesh"))
implementation(project(":orx-noise"))
} }
} }

View File

@@ -3,6 +3,9 @@ package org.openrndr.extra.mesh.noise
import org.openrndr.extra.mesh.IIndexedPolygon import org.openrndr.extra.mesh.IIndexedPolygon
import org.openrndr.extra.mesh.IMeshData import org.openrndr.extra.mesh.IMeshData
import org.openrndr.extra.mesh.IVertexData import org.openrndr.extra.mesh.IVertexData
import org.openrndr.extra.noise.fhash1D
import org.openrndr.extra.noise.uhash11
import org.openrndr.extra.noise.uhash1D
import org.openrndr.math.Vector3 import org.openrndr.math.Vector3
import kotlin.math.sqrt import kotlin.math.sqrt
import kotlin.random.Random import kotlin.random.Random
@@ -20,6 +23,23 @@ fun uniformBarycentric(random: Random = Random.Default): Vector3 {
return Vector3(b0, b1, 1.0 - b0 - b1) return Vector3(b0, b1, 1.0 - b0 - b1)
} }
/**
* Generate a uniformly distributed barycentric coordinate
* @param random a random number generator
*/
fun hashBarycentric(seed: Int, x: Int): Vector3 {
val u = fhash1D(seed, x)
val v = fhash1D(seed, u.toRawBits().toInt() - x)
val su0 = sqrt(u)
val b0 = 1.0 - su0
val b1 = v * su0
return Vector3(b0, b1, 1.0 - b0 - b1)
}
/** /**
* Generate a uniformly distributed point that lies inside this [IIndexedPolygon] * Generate a uniformly distributed point that lies inside this [IIndexedPolygon]
* @param vertexData vertex data used to resolve positions * @param vertexData vertex data used to resolve positions
@@ -33,6 +53,19 @@ fun IIndexedPolygon.uniform(vertexData: IVertexData, random: Random = Random.Def
return x[0] * b.x + x[1] * b.y + x[2] * b.z return x[0] * b.x + x[1] * b.y + x[2] * b.z
} }
/**
* Generate a uniformly distributed point that lies inside this [IIndexedPolygon]
* @param vertexData vertex data used to resolve positions
* @param random a random number generator
*/
fun IIndexedPolygon.hash(vertexData: IVertexData, seed:Int, x: Int): Vector3 {
require(positions.size == 3) { "polygon must be a triangle"}
val s = vertexData.positions.slice(positions)
val b = hashBarycentric(seed, x)
return s[0] * b.x + s[1] * b.y + s[2] * b.z
}
internal fun IIndexedPolygon.area(vertexData: IVertexData): Double { internal fun IIndexedPolygon.area(vertexData: IVertexData): Double {
require(positions.size == 3) { "polygon must be a triangle"} require(positions.size == 3) { "polygon must be a triangle"}
val x = vertexData.positions.slice(positions) val x = vertexData.positions.slice(positions)
@@ -62,4 +95,27 @@ fun IMeshData.uniform(count: Int, random: Random = Random.Default): List<Vector3
} }
} }
return result return result
}
/**
* Generate points on the surface described by the mesh data
*/
fun IMeshData.hash(count: Int, seed:Int, x: Int): List<Vector3> {
val triangulated = triangulate()
val result = mutableListOf<Vector3>()
val totalArea = triangulated.polygons.sumOf { it.area(vertexData) }
val randoms = (0 until count).map {
Pair(x + it, fhash1D(seed, x + it) * totalArea)
}.sortedBy { it.second }
var idx = 0
var sum = 0.0
for (t in triangulated.polygons) {
sum += t.area(vertexData)
while (idx <= randoms.lastIndex && sum > randoms[idx].second) {
result.add(t.hash(vertexData, seed xor 0x7f7f7f, randoms[idx].first))
idx++
}
}
return result
} }

View File

@@ -0,0 +1,48 @@
import org.openrndr.application
import org.openrndr.draw.DrawPrimitive
import org.openrndr.draw.isolated
import org.openrndr.draw.shadeStyle
import org.openrndr.extra.camera.Orbital
import org.openrndr.extra.mesh.noise.hash
import org.openrndr.extra.objloader.loadOBJMeshData
import org.openrndr.extra.mesh.noise.uniform
import org.openrndr.extra.meshgenerators.sphereMesh
import org.openrndr.math.Vector3
import java.io.File
import kotlin.math.cos
import kotlin.random.Random
/**
* Demonstrate uniform point on mesh generation using hash functions
*/
fun main() {
application {
configure {
width = 720
height = 720
}
program {
val mesh = loadOBJMeshData(File("demo-data/obj-models/suzanne/Suzanne.obj")).toMeshData()
val sphere = sphereMesh(radius = 0.01)
extend(Orbital()) {
eye = Vector3(0.0, 0.0, 2.0)
}
extend {
val points = mesh.hash((1000 + (cos(seconds)*0.5+0.5)*9000).toInt(), 808, (seconds*10000).toInt())
drawer.shadeStyle = shadeStyle {
fragmentTransform = "x_fill = vec4(v_viewNormal*0.5+0.5, 1.0);"
}
for (point in points) {
drawer.isolated {
drawer.translate(point)
drawer.vertexBuffer(sphere, DrawPrimitive.TRIANGLES)
}
}
}
}
}
}

View File

@@ -1,35 +1,25 @@
package org.openrndr.extra.noise package org.openrndr.extra.noise
import org.openrndr.extra.hashgrid.HashGrid import org.openrndr.extra.hashgrid.HashGrid
import org.openrndr.extra.noise.shapes.hash
import org.openrndr.extra.noise.shapes.uniform
import org.openrndr.math.Vector2 import org.openrndr.math.Vector2
import org.openrndr.shape.* import org.openrndr.shape.*
import kotlin.random.Random import kotlin.random.Random
/** /**
* Returns a random [Vector2] point located inside a [ShapeProvider] while * Generates specified amount of random points that lie inside the [Shape].
* maintaining a distance to the edge of the shape of [distanceToEdge] units. *
* @param pointCount The number of points to generate.
* @param random The [Random] number generator to use, defaults to [Random.Default].
*/ */
fun ShapeProvider.uniform(distanceToEdge: Double = 0.0, random: Random = Random.Default): Vector2 { fun ShapeProvider.uniform(pointCount: Int, random: Random = Random.Default): List<Vector2> {
val shape = shape return shape.triangulation.uniform(pointCount, random)
require(!shape.empty)
var attempts = 0
val innerBounds = shape.bounds.offsetEdges(-distanceToEdge.coerceAtLeast(0.0))
return Vector2.uniformSequence(innerBounds, random).first {
attempts++
require(attempts < 100)
if (distanceToEdge == 0.0) {
shape.contains(it)
} else {
shape.contains(it) && shape.contours.minOf { c -> c.nearest(it).position.distanceTo(it) } > distanceToEdge
}
}
} }
/** fun ShapeProvider.hash(pointCount: Int, seed: Int, x: Int): List<Vector2> {
* Generate [sampleCount] uniformly distributed points inside the area of [ShapeProvider] return shape.triangulation.hash(pointCount, seed, x)
*/ }
fun ShapeProvider.uniform(sampleCount: Int, random: Random = Random.Default) : List<Vector2> = shape.triangulation.uniform(sampleCount, random)
/** /**
* Returns a list of pairs in which the first component is a radius and the * Returns a list of pairs in which the first component is a radius and the

View File

@@ -1,26 +0,0 @@
package org.openrndr.extra.noise
import org.openrndr.math.Vector2
import org.openrndr.shape.Triangle
import kotlin.random.Random
/**
* Generate [count] uniform samples from a list of [Triangle]s
*/
fun List<Triangle>.uniform(count: Int, random: Random = Random.Default): List<Vector2> {
val totalArea = this.sumOf { it.area }
val randoms = (0 until count).map {
Double.uniform(0.0, totalArea, random = random)
}.sorted()
val result = mutableListOf<Vector2>()
var idx = 0
var sum = 0.0
for (t in this) {
sum += t.area
while (idx <= randoms.lastIndex && sum > randoms[idx]) {
result.add(t.randomPoint(random))
idx++
}
}
return result
}

View File

@@ -23,6 +23,12 @@ fun Double.Companion.uniform(
) = ) =
(random.nextDouble() * (max - min)) + min (random.nextDouble() * (max - min)) + min
fun Double.Companion.hash(
seed: Int, x: Int,
min: Double = -1.0, max: Double = 1.0
) = fhash1D(seed, x) * (max - min) + min
fun Vector2.Companion.uniform( fun Vector2.Companion.uniform(
min: Vector2 = -ONE, max: Vector2 = ONE, min: Vector2 = -ONE, max: Vector2 = ONE,
random: Random = Random.Default random: Random = Random.Default
@@ -32,12 +38,28 @@ fun Vector2.Companion.uniform(
Double.uniform(min.y, max.y, random) Double.uniform(min.y, max.y, random)
) )
fun Vector2.Companion.hash(
seed: Int, x: Int,
min: Vector2 = -ONE, max: Vector2 = ONE
) =
Vector2(
Double.hash(seed, x, min.x, max.x),
Double.hash(seed xor 0x7f7f7f7f, x, min.y, max.y)
)
fun Vector2.Companion.uniform( fun Vector2.Companion.uniform(
min: Double = -1.0, max: Double = 1.0, min: Double = -1.0, max: Double = 1.0,
random: Random = Random.Default random: Random = Random.Default
) = ) =
Vector2.uniform(Vector2(min, min), Vector2(max, max), random) Vector2.uniform(Vector2(min, min), Vector2(max, max), random)
fun Vector2.Companion.hash(
seed: Int, x: Int,
min: Double = -1.0, max: Double = 1.0,
) =
Vector2.hash(seed, x, Vector2(min, min), Vector2(max, max))
fun Vector2.Companion.uniform( fun Vector2.Companion.uniform(
rect: Rectangle, rect: Rectangle,
random: Random = Random.Default random: Random = Random.Default
@@ -78,7 +100,7 @@ fun Vector2.Companion.uniformRing(
val eps = 1E-6 val eps = 1E-6
if ( abs(innerRadius - outerRadius) < eps) { if (abs(innerRadius - outerRadius) < eps) {
val angle = Double.uniform(-180.0, 180.0, random) val angle = Double.uniform(-180.0, 180.0, random)
return Polar(angle, innerRadius).cartesian return Polar(angle, innerRadius).cartesian

View File

@@ -0,0 +1,28 @@
package org.openrndr.extra.noise.shapes
import org.openrndr.extra.noise.uhash11
import org.openrndr.math.Vector3
import org.openrndr.shape.Box
import kotlin.random.Random
fun Box.uniform(random: Random = Random.Default): Vector3 {
val x = random.nextDouble() * width + corner.x
val y = random.nextDouble() * height + corner.y
val z = random.nextDouble() * depth + corner.z
return Vector3(x, y ,z)
}
fun Box.hash(seed: Int, x: Int): Vector3 {
val ux = uhash11(seed.toUInt() + uhash11(x.toUInt()))
val uy = uhash11(ux + x.toUInt())
val uz = uhash11(uy + x.toUInt())
val fx = ux.toDouble() / UInt.MAX_VALUE.toDouble()
val fy = uy.toDouble() / UInt.MAX_VALUE.toDouble()
val fz = uz.toDouble() / UInt.MAX_VALUE.toDouble()
val x = fx * width + corner.x
val y = fy * height + corner.y
val z = fz * depth + corner.z
return Vector3(x, y, z)
}

View File

@@ -0,0 +1,27 @@
package org.openrndr.extra.noise.shapes
import org.openrndr.extra.noise.fhash1D
import org.openrndr.extra.noise.hash
import org.openrndr.math.Polar
import org.openrndr.math.Vector2
import org.openrndr.shape.Circle
import kotlin.math.sqrt
import kotlin.random.Random
/**
* Generate a uniformly distributed random point inside [Circle]
*/
fun Circle.hash(seed: Int, x: Int): Vector2 {
val r = radius * sqrt(fhash1D(seed, x))
val phi = 360.0 * fhash1D(seed xor 0x7f7f_7f7f, x)
return Polar(phi, r).cartesian + center
}
/**
* Generate a uniformly distributed random point inside [Circle]
*/
fun Circle.uniform(random: Random = Random.Default): Vector2 {
val r = radius * sqrt(random.nextDouble())
val phi = 360.0 * random.nextDouble()
return Polar(phi, r).cartesian + center
}

View File

@@ -0,0 +1,24 @@
package org.openrndr.extra.noise.shapes
import org.openrndr.extra.noise.uhash11
import org.openrndr.math.Vector2
import org.openrndr.shape.Rectangle
import kotlin.random.Random
fun Rectangle.uniform(random: Random = Random.Default): Vector2 {
val x = random.nextDouble() * width + corner.x
val y = random.nextDouble() * height + corner.y
return Vector2(x, y)
}
fun Rectangle.hash(seed: Int, x: Int): Vector2 {
val ux = uhash11(seed.toUInt() + uhash11(x.toUInt()))
val uy = uhash11(ux + x.toUInt())
val fx = ux.toDouble() / UInt.MAX_VALUE.toDouble()
val fy = uy.toDouble() / UInt.MAX_VALUE.toDouble()
val x = fx * width + corner.x
val y = fy * height + corner.y
return Vector2(x, y)
}

View File

@@ -0,0 +1,58 @@
package org.openrndr.extra.noise.shapes
import org.openrndr.extra.noise.fhash1D
import org.openrndr.extra.noise.uniform
import org.openrndr.math.Vector2
import org.openrndr.shape.Triangle
import kotlin.random.Random
/**
* Generate [count] uniform samples from a list of [Triangle]s
*/
fun List<Triangle>.uniform(count: Int, random: Random = Random.Default): List<Vector2> {
val totalArea = this.sumOf { it.area }
val randoms = (0 until count).map {
Double.uniform(0.0, totalArea, random = random)
}.sorted()
val result = mutableListOf<Vector2>()
var idx = 0
var sum = 0.0
for (t in this) {
sum += t.area
while (idx <= randoms.lastIndex && sum > randoms[idx]) {
result.add(t.uniform(random))
idx++
}
}
return result
}
fun List<Triangle>.hash(count: Int, seed: Int = 0, x: Int = 0): List<Vector2> {
val totalArea = this.sumOf { it.area }
val randoms = (0 until count).map {
Pair(x + it, fhash1D(seed, x + it) * totalArea)
}.sortedBy { it.second }
val result = mutableListOf<Vector2>()
var idx = 0
var sum = 0.0
for (t in this) {
sum += t.area
while (idx <= randoms.lastIndex && sum > randoms[idx].second) {
result.add(t.hash(seed, randoms[idx].first))
idx++
}
}
return result
}
/** Generates a random point that lies inside the [Triangle]. */
fun Triangle.uniform(random: Random = Random.Default): Vector2 {
return position(random.nextDouble(), random.nextDouble())
}
fun Triangle.hash(seed: Int, x: Int): Vector2 {
val u = fhash1D(seed, x)
val v = fhash1D(seed, u.toRawBits().toInt() + x)
return position(u, v)
}

View File

@@ -0,0 +1,33 @@
import org.openrndr.application
import org.openrndr.extra.noise.shapes.hash
import org.openrndr.extra.noise.shapes.uniform
import org.openrndr.shape.Circle
import kotlin.random.Random
fun main() {
application {
configure {
width = 720
height = 720
}
program {
extend {
val b = drawer.bounds
val b0 = b.sub(0.0, 0.0, 0.5, 1.0).offsetEdges(-10.0)
val b1 = b.sub(0.5, 0.0, 1.0, 1.0).offsetEdges(-10.0)
val c0 = Circle(b0.center, b0.width/2.0)
val c1 = Circle(b1.center, b1.width/2.0)
val r = Random(0)
for (i in 0 until 2000) {
drawer.circle(c0.uniform(r), 2.0)
drawer.circle(c1.hash(909, i),2.0)
}
}
}
}
}

View File

@@ -0,0 +1,29 @@
import org.openrndr.application
import org.openrndr.extra.noise.shapes.hash
import org.openrndr.extra.noise.shapes.uniform
import kotlin.random.Random
fun main() {
application {
configure {
width = 720
height = 720
}
program {
extend {
val b = drawer.bounds
val b0 = b.sub(0.0, 0.0, 0.5, 1.0).offsetEdges(-10.0)
val b1 = b.sub(0.5, 0.0, 1.0, 1.0).offsetEdges(-10.0)
val r = Random(0)
for (i in 0 until 20000) {
drawer.circle(b0.uniform(r), 2.0)
drawer.circle(b1.hash(909, i),2.0)
}
}
}
}
}

View File

@@ -1,8 +1,7 @@
import org.openrndr.application import org.openrndr.application
import org.openrndr.color.ColorRGBa import org.openrndr.color.ColorRGBa
import org.openrndr.extra.noise.uniform import org.openrndr.extra.noise.shapes.hash
import org.openrndr.shape.Triangle import org.openrndr.shape.Triangle
import kotlin.random.Random
/** /**
* Demonstrate the generation of uniformly distributed points inside a list of triangles * Demonstrate the generation of uniformly distributed points inside a list of triangles
@@ -17,8 +16,10 @@ fun main() {
program { program {
val r = drawer.bounds.offsetEdges(-100.0) val r = drawer.bounds.offsetEdges(-100.0)
val triangle = Triangle(r.position(0.5, 0.0), r.position(0.0, 1.0), r.position(1.0, 1.0)) val triangle = Triangle(r.position(0.5, 0.0), r.position(0.0, 1.0), r.position(1.0, 1.0))
val pts = listOf(triangle).uniform(1000, Random(0)) //val pts = listOf(triangle).uniform(1000, Random(0))
extend { extend {
val pts = listOf(triangle).hash(1000, 0, (seconds*500.0).toInt())
drawer.clear(ColorRGBa.PINK) drawer.clear(ColorRGBa.PINK)
drawer.stroke = null drawer.stroke = null
drawer.contour(triangle.contour) drawer.contour(triangle.contour)

View File

@@ -6,6 +6,7 @@ import org.openrndr.extra.shapes.primitives.intersection
/** /**
* Demonstrate rectangle-rectangle intersection * Demonstrate rectangle-rectangle intersection
* @see <img src="https://raw.githubusercontent.com/openrndr/orx/media/orx-shapes/images/primitives-DemoRectangleIntersection01Kt.png">
*/ */
fun main() { fun main() {
application { application {