[orx-mesh, orx-mesh-noise] Add orx-mesh-noise

This commit is contained in:
Edwin Jakobs
2024-09-17 16:55:07 +02:00
parent 42d40c30b1
commit b6c037079b
22 changed files with 191 additions and 31 deletions

View File

@@ -0,0 +1,28 @@
plugins {
org.openrndr.extra.convention.`kotlin-multiplatform`
}
kotlin {
sourceSets {
val commonMain by getting {
dependencies {
api(libs.openrndr.application)
api(libs.openrndr.math)
api(libs.openrndr.shape)
api(project(":orx-mesh"))
}
}
val jvmDemo by getting {
dependencies {
api(libs.openrndr.shape)
implementation(project(":orx-shapes"))
implementation(project(":orx-mesh"))
implementation(project(":orx-mesh-generators"))
implementation(project(":orx-obj-loader"))
implementation(project(":orx-noise"))
implementation(project(":orx-camera"))
}
}
}
}

View File

@@ -0,0 +1,65 @@
package org.openrndr.extra.mesh.noise
import org.openrndr.extra.mesh.IIndexedPolygon
import org.openrndr.extra.mesh.IMeshData
import org.openrndr.extra.mesh.IVertexData
import org.openrndr.math.Vector3
import kotlin.math.sqrt
import kotlin.random.Random
/**
* Generate a uniformly distributed barycentric coordinate
* @param random a random number generator
*/
fun uniformBarycentric(random: Random = Random.Default): Vector3 {
val u = random.nextDouble()
val v = random.nextDouble()
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]
* @param vertexData vertex data used to resolve positions
* @param random a random number generator
*/
fun IIndexedPolygon.uniform(vertexData: IVertexData, random: Random = Random.Default): Vector3 {
require(positions.size == 3) { "polygon must be a triangle"}
val x = vertexData.positions.slice(positions)
val b = uniformBarycentric(random)
return x[0] * b.x + x[1] * b.y + x[2] * b.z
}
internal fun IIndexedPolygon.area(vertexData: IVertexData): Double {
require(positions.size == 3) { "polygon must be a triangle"}
val x = vertexData.positions.slice(positions)
val u = x[1] - x[0]
val v = x[2] - x[0]
return u.areaBetween(v) / 2.0
}
/**
* Generate points on the surface described by the mesh data
*/
fun IMeshData.uniform(count: Int, random: Random = Random.Default): List<Vector3> {
val triangulated = triangulate()
val result = mutableListOf<Vector3>()
val totalArea = triangulated.polygons.sumOf { it.area(vertexData) }
val randoms = (0 until count).map {
random.nextDouble(totalArea)
}.sorted()
var idx = 0
var sum = 0.0
for (t in triangulated.polygons) {
sum += t.area(vertexData)
while (idx <= randoms.lastIndex && sum > randoms[idx]) {
result.add(t.uniform(vertexData, random))
idx++
}
}
return result
}

View File

@@ -0,0 +1,43 @@
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.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.random.Random
/**
* Demonstrate uniform point on mesh generation
*/
fun main() {
application {
configure {
width = 720
height = 720
}
program {
val mesh = loadOBJMeshData(File("demo-data/obj-models/suzanne/Suzanne.obj")).toMeshData()
val points = mesh.uniform(1000, Random(0))
val sphere = sphereMesh(radius = 0.1)
extend(Orbital()) {
eye = Vector3(0.0, 0.0, 2.0)
}
extend {
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,4 +1,4 @@
package org.openrndr.extra.objloader package org.openrndr.extra.mesh
/** /**
* Compound mesh data interface * Compound mesh data interface
@@ -8,6 +8,8 @@ interface ICompoundMeshData {
val compounds: Map<String, IMeshData> val compounds: Map<String, IMeshData>
fun triangulate(): ICompoundMeshData fun triangulate(): ICompoundMeshData
fun toMeshData(): IMeshData
} }
class CompoundMeshData( class CompoundMeshData(
@@ -15,15 +17,15 @@ class CompoundMeshData(
override val compounds: Map<String, MeshData> override val compounds: Map<String, MeshData>
) : ICompoundMeshData { ) : ICompoundMeshData {
init {
}
override fun triangulate(): CompoundMeshData { override fun triangulate(): CompoundMeshData {
return CompoundMeshData(vertexData, compounds.mapValues { return CompoundMeshData(vertexData, compounds.mapValues {
it.value.triangulate() it.value.triangulate()
}) })
} }
override fun toMeshData(): MeshData {
return MeshData(vertexData, compounds.values.flatMap { it.polygons })
}
} }
class MutableCompoundMeshData( class MutableCompoundMeshData(
@@ -36,6 +38,11 @@ class MutableCompoundMeshData(
vertexData, vertexData,
compounds.mapValues { compounds.mapValues {
it.value.triangulate() it.value.triangulate()
}.toMutableMap()) }.toMutableMap()
)
}
override fun toMeshData(): IMeshData {
return MutableMeshData(vertexData, compounds.values.flatMap { it.polygons }.toMutableList())
} }
} }

View File

@@ -1,4 +1,4 @@
package org.openrndr.extra.objloader package org.openrndr.extra.mesh
import org.openrndr.draw.VertexBuffer import org.openrndr.draw.VertexBuffer
import org.openrndr.draw.vertexBuffer import org.openrndr.draw.vertexBuffer

View File

@@ -1,4 +1,4 @@
package org.openrndr.extra.objloader package org.openrndr.extra.mesh
import org.openrndr.math.Matrix44 import org.openrndr.math.Matrix44
import org.openrndr.math.Vector2 import org.openrndr.math.Vector2

View File

@@ -1,4 +1,4 @@
package org.openrndr.extra.objloader package org.openrndr.extra.mesh
import kotlin.jvm.JvmRecord import kotlin.jvm.JvmRecord
@@ -21,7 +21,10 @@ data class MeshData(
override val polygons: List<IndexedPolygon>, override val polygons: List<IndexedPolygon>,
) : IMeshData { ) : IMeshData {
override fun triangulate(): MeshData { override fun triangulate(): MeshData {
return copy(polygons = polygons.flatMap { polygon -> polygon.triangulate(vertexData) }) return if (isTriangular()) {
this
} else
copy(polygons = polygons.flatMap { polygon -> polygon.triangulate(vertexData) })
} }
override fun toPolygons(): List<Polygon> { override fun toPolygons(): List<Polygon> {
@@ -40,7 +43,11 @@ data class MutableMeshData(
override val polygons: MutableList<IndexedPolygon> override val polygons: MutableList<IndexedPolygon>
) : IMeshData { ) : IMeshData {
override fun triangulate(): MutableMeshData { override fun triangulate(): MutableMeshData {
return copy(polygons = polygons.flatMap { it.triangulate(vertexData) }.toMutableList()) return if (isTriangular()) {
this
} else {
copy(polygons = polygons.flatMap { it.triangulate(vertexData) }.toMutableList())
}
} }
override fun toPolygons(): List<Polygon> { override fun toPolygons(): List<Polygon> {

View File

@@ -1,4 +1,4 @@
package org.openrndr.extra.objloader package org.openrndr.extra.mesh
import org.openrndr.color.ColorRGBa import org.openrndr.color.ColorRGBa
import org.openrndr.draw.VertexBuffer import org.openrndr.draw.VertexBuffer
@@ -18,7 +18,14 @@ internal val objVertexFormat = vertexFormat {
} }
/** /**
* Converts a [MeshData] instance into a [VertexBuffer] * Determine if [IMeshData] is triangular by checking if each polygon has exactly 3 vertices
*/
fun IMeshData.isTriangular(): Boolean {
return polygons.all { it.positions.size == 3 }
}
/**
* Convert a [MeshData] instance into a [VertexBuffer]
*/ */
fun IMeshData.toVertexBuffer(elementOffset: Int = 0, vertexBuffer: VertexBuffer? = null): VertexBuffer { fun IMeshData.toVertexBuffer(elementOffset: Int = 0, vertexBuffer: VertexBuffer? = null): VertexBuffer {
val objects = triangulate().toPolygons() val objects = triangulate().toPolygons()

View File

@@ -1,4 +1,4 @@
package org.openrndr.extra.objloader package org.openrndr.extra.mesh
import org.openrndr.color.ColorRGBa import org.openrndr.color.ColorRGBa
import org.openrndr.math.Matrix44 import org.openrndr.math.Matrix44

View File

@@ -1,4 +1,4 @@
package org.openrndr.extra.objloader package org.openrndr.extra.mesh
import org.openrndr.color.ColorRGBa import org.openrndr.color.ColorRGBa
import org.openrndr.math.Vector2 import org.openrndr.math.Vector2

View File

@@ -1,4 +1,4 @@
package org.openrndr.extra.objloader package org.openrndr.extra.mesh
import org.openrndr.math.Vector3 import org.openrndr.math.Vector3

View File

@@ -1,7 +1,9 @@
package org.openrndr.extra.mesh
import org.openrndr.color.ColorRGBa import org.openrndr.color.ColorRGBa
import org.openrndr.draw.VertexBuffer import org.openrndr.draw.VertexBuffer
import org.openrndr.extra.objloader.Polygon import org.openrndr.extra.mesh.Polygon
import org.openrndr.extra.objloader.objVertexFormat import org.openrndr.extra.mesh.objVertexFormat
import org.openrndr.math.Vector2 import org.openrndr.math.Vector2
import org.openrndr.math.Vector3 import org.openrndr.math.Vector3
import java.nio.ByteBuffer import java.nio.ByteBuffer

View File

@@ -1,4 +1,4 @@
package org.openrndr.extra.objloader package org.openrndr.extra.mesh
import org.openrndr.color.ColorRGBa import org.openrndr.color.ColorRGBa
import org.openrndr.draw.VertexBuffer import org.openrndr.draw.VertexBuffer

View File

@@ -1,4 +1,4 @@
package org.openrndr.extra.objloader package org.openrndr.extra.mesh
/** /**
* Convert mesh data to Wavefront OBJ representation * Convert mesh data to Wavefront OBJ representation

View File

@@ -1,6 +1,6 @@
import org.openrndr.application import org.openrndr.application
import org.openrndr.extra.objloader.loadOBJMeshData import org.openrndr.extra.mesh.loadOBJMeshData
import org.openrndr.extra.objloader.toObj import org.openrndr.extra.mesh.toObj
import java.io.File import java.io.File
fun main() { fun main() {

View File

@@ -3,7 +3,7 @@ import org.openrndr.color.ColorRGBa
import org.openrndr.draw.DepthTestPass import org.openrndr.draw.DepthTestPass
import org.openrndr.draw.DrawPrimitive import org.openrndr.draw.DrawPrimitive
import org.openrndr.draw.shadeStyle import org.openrndr.draw.shadeStyle
import org.openrndr.extra.objloader.loadOBJasVertexBuffer import org.openrndr.extra.mesh.loadOBJasVertexBuffer
import org.openrndr.math.Vector3 import org.openrndr.math.Vector3
fun main() = application { fun main() = application {

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.objloader.loadOBJasVertexBuffer import org.openrndr.extra.mesh.loadOBJasVertexBuffer
import org.openrndr.extra.objloader.saveOBJ import org.openrndr.extra.mesh.saveOBJ
fun main() = application { fun main() = application {
configure { configure {

View File

@@ -2,7 +2,7 @@ import org.openrndr.application
import org.openrndr.draw.loadFont import org.openrndr.draw.loadFont
import org.openrndr.extra.meshgenerators.buildTriangleMesh import org.openrndr.extra.meshgenerators.buildTriangleMesh
import org.openrndr.extra.meshgenerators.sphere import org.openrndr.extra.meshgenerators.sphere
import org.openrndr.extra.objloader.saveOBJ import org.openrndr.extra.mesh.saveOBJ
fun main() = application { fun main() = application {
configure { configure {

View File

@@ -8,9 +8,9 @@ import org.openrndr.draw.DrawPrimitive
import org.openrndr.draw.TransformTarget import org.openrndr.draw.TransformTarget
import org.openrndr.draw.shadeStyle import org.openrndr.draw.shadeStyle
import org.openrndr.extra.camera.Orbital import org.openrndr.extra.camera.Orbital
import org.openrndr.extra.objloader.readObjMeshData import org.openrndr.extra.mesh.readObjMeshData
import org.openrndr.extra.objloader.loadOBJasVertexBuffer import org.openrndr.extra.mesh.loadOBJasVertexBuffer
import org.openrndr.extra.objloader.wireframe import org.openrndr.extra.mesh.wireframe
import org.openrndr.math.Vector3 import org.openrndr.math.Vector3
import org.openrndr.shape.Path3D import org.openrndr.shape.Path3D
import java.io.File import java.io.File

View File

@@ -1,4 +1,4 @@
package org.openrndr.extra.objloader package org.openrndr.extra.mesh
import org.openrndr.draw.VertexBuffer import org.openrndr.draw.VertexBuffer
import java.io.File import java.io.File

View File

@@ -1,4 +1,4 @@
package org.openrndr.extra.objloader package org.openrndr.extra.mesh
import org.openrndr.draw.VertexBuffer import org.openrndr.draw.VertexBuffer
import java.io.File import java.io.File

View File

@@ -48,6 +48,7 @@ include(
"orx-jvm:orx-keyframer", "orx-jvm:orx-keyframer",
"orx-mesh", "orx-mesh",
"orx-mesh-generators", "orx-mesh-generators",
"orx-mesh-noise",
"orx-jvm:orx-minim", "orx-jvm:orx-minim",
"orx-jvm:orx-kotlin-parser", "orx-jvm:orx-kotlin-parser",
"orx-jvm:orx-midi", "orx-jvm:orx-midi",