Skip to content

Commit

Permalink
[orx-mesh, orx-obj-loader] Separate into commonMain and jvmMain
Browse files Browse the repository at this point in the history
  • Loading branch information
edwinRNDR committed Sep 16, 2024
1 parent 8bccf54 commit ed55899
Show file tree
Hide file tree
Showing 20 changed files with 425 additions and 86 deletions.
13 changes: 12 additions & 1 deletion orx-mesh/src/commonMain/kotlin/CompoundMeshData.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
package org.openrndr.extra.objloader

/**
* Compound mesh data interface
*/
interface ICompoundMeshData {
val vertexData: IVertexData
val compounds: Map<String, IMeshData>
Expand All @@ -12,6 +15,10 @@ class CompoundMeshData(
override val compounds: Map<String, MeshData>
) : ICompoundMeshData {

init {

}

override fun triangulate(): CompoundMeshData {
return CompoundMeshData(vertexData, compounds.mapValues {
it.value.triangulate()
Expand All @@ -25,6 +32,10 @@ class MutableCompoundMeshData(
) : ICompoundMeshData {

override fun triangulate(): MutableCompoundMeshData {
TODO("Not yet implemented")
return MutableCompoundMeshData(
vertexData,
compounds.mapValues {
it.value.triangulate()
}.toMutableMap())
}
}
4 changes: 2 additions & 2 deletions orx-mesh/src/commonMain/kotlin/CompoundMeshDataExtensions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@ fun ICompoundMeshData.toVertexBuffer(): VertexBuffer {
return vertexBuffer
}

fun ICompoundMeshData.flattenPolygons(): Map<String, List<IPolygon>> {
return compounds.mapValues { it.value.flattenPolygons() }
fun ICompoundMeshData.toPolygons(): Map<String, List<IPolygon>> {
return compounds.mapValues { it.value.toPolygons() }
}
52 changes: 50 additions & 2 deletions orx-mesh/src/commonMain/kotlin/IndexedPolygon.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,38 @@ import kotlin.math.abs
import kotlin.math.atan2
import kotlin.math.round

/**
* Indexed polygon interface
*/
interface IIndexedPolygon {
/**
* Position indices
*/
val positions: List<Int>

/**
* Texture coordinate indices, optional
*/
val textureCoords: List<Int>

/**
* Normal indices, optional
*/
val normals: List<Int>

/**
* Color indices, optional
*/
val colors: List<Int>

/**
* Tangents, optional
*/
val tangents: List<Int>

/**
* Bitangents, optional
*/
val bitangents: List<Int>

fun base(vertexData: IVertexData): Matrix44 {
Expand All @@ -30,6 +56,11 @@ interface IIndexedPolygon {
)
}

/**
* Determine if polygon is planar
* @param vertexData the vertex data
* @param eps error tolerance
*/
fun isPlanar(vertexData: IVertexData, eps: Double = 1E-2): Boolean {
fun normal(i: Int): Vector3 {
val p0 = vertexData.positions[positions[(i - 1).mod(positions.size)]]
Expand All @@ -48,6 +79,9 @@ interface IIndexedPolygon {
}
}

/**
* Determine polygon convexity
*/
fun isConvex(vertexData: IVertexData): Boolean {
val planar = base(vertexData).inversed

Expand Down Expand Up @@ -99,10 +133,16 @@ interface IIndexedPolygon {
return abs(round(angleSum / (2 * PI))) == 1.0
}

/**
* Convert to [IPolygon]
* @param vertexData the vertex data required to build the [IPolygon]
*/
fun toPolygon(vertexData: IVertexData): IPolygon
}


/**
* Immutable indexed polygon implementation
*/
data class IndexedPolygon(
override val positions: List<Int>,
override val textureCoords: List<Int>,
Expand All @@ -113,7 +153,7 @@ data class IndexedPolygon(

) : IIndexedPolygon {

fun tessellate(vertexData: IVertexData): List<IndexedPolygon> {
private fun tessellate(vertexData: IVertexData): List<IndexedPolygon> {
val points = vertexData.positions.slice(positions.toList())
val triangles = org.openrndr.shape.triangulate(listOf(points))

Expand All @@ -129,6 +169,11 @@ data class IndexedPolygon(
}
}

/**
* Convert to a list of triangle [IndexedPolygon]
*
* Supports non-planar and non-convex polygons
*/
fun triangulate(vertexData: IVertexData): List<IndexedPolygon> {
return when {
positions.size == 3 -> listOf(this)
Expand Down Expand Up @@ -180,6 +225,9 @@ data class IndexedPolygon(
}
}

/**
* Mutable indexed polygon implementation
*/
data class MutableIndexedPolygon(
override val positions: MutableList<Int>,
override val textureCoords: MutableList<Int>,
Expand Down
16 changes: 12 additions & 4 deletions orx-mesh/src/commonMain/kotlin/MeshData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,19 @@ package org.openrndr.extra.objloader

import kotlin.jvm.JvmRecord

/**
* Mesh data interface
*/
interface IMeshData {
val vertexData: IVertexData
val polygons: List<IIndexedPolygon>
fun triangulate(): IMeshData
fun flattenPolygons(): List<IPolygon>
fun toPolygons(): List<IPolygon>
}

/**
* Immutable mesh data implementation
*/
@JvmRecord
data class MeshData(
override val vertexData: VertexData,
Expand All @@ -18,14 +24,17 @@ data class MeshData(
return copy(polygons = polygons.flatMap { polygon -> polygon.triangulate(vertexData) })
}

override fun flattenPolygons(): List<Polygon> {
override fun toPolygons(): List<Polygon> {
return polygons.map { ip ->
ip.toPolygon(vertexData)
}
}
}


/**
* Mutable mesh data implementation
*/
data class MutableMeshData(
override val vertexData: MutableVertexData,
override val polygons: MutableList<IndexedPolygon>
Expand All @@ -34,8 +43,7 @@ data class MutableMeshData(
return copy(polygons = polygons.flatMap { it.triangulate(vertexData) }.toMutableList())
}

override fun flattenPolygons(): List<Polygon> {
override fun toPolygons(): List<Polygon> {
return polygons.map { it.toPolygon(vertexData) }

}
}
11 changes: 8 additions & 3 deletions orx-mesh/src/commonMain/kotlin/MeshDataExtensions.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.openrndr.extra.objloader

import org.openrndr.color.ColorRGBa
import org.openrndr.draw.VertexBuffer
import org.openrndr.draw.VertexFormat
import org.openrndr.draw.vertexBuffer
Expand All @@ -13,13 +14,14 @@ internal val objVertexFormat = vertexFormat {
position(3)
normal(3)
textureCoordinate(2)
color(4)
}

/**
* Converts a [MeshData] instance into a [VertexBuffer]
*/
fun IMeshData.toVertexBuffer(elementOffset: Int = 0, vertexBuffer: VertexBuffer? = null): VertexBuffer {
val objects = triangulate().flattenPolygons()
val objects = triangulate().toPolygons()
val triangleCount = objects.size
val vertexBuffer = vertexBuffer ?: vertexBuffer(objVertexFormat, triangleCount * 3)

Expand All @@ -40,11 +42,14 @@ fun IMeshData.toVertexBuffer(elementOffset: Int = 0, vertexBuffer: VertexBuffer?
} else {
write(Vector2.ZERO)
}
if (it.colors.isNotEmpty()) {
write(it.colors[i])
} else {
write(ColorRGBa.WHITE)
}
}
}
}


vertexBuffer.shadow.destroy()
return vertexBuffer
}
50 changes: 48 additions & 2 deletions orx-mesh/src/commonMain/kotlin/Polygon.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ import org.openrndr.shape.Box
import kotlin.math.max
import kotlin.math.min


/**
* 3D Polygon interface
*/
interface IPolygon {
val positions: List<Vector3>
val normals: List<Vector3>
Expand All @@ -20,7 +24,7 @@ interface IPolygon {
}

/**
* A 3D Polygon
* Immutable 3D Polygon implementation
*
* @property positions Vertex 3D positions
* @property normals Vertex 3D normals
Expand Down Expand Up @@ -54,6 +58,9 @@ class Polygon(
}
}

/**
* Mutable 3D Polygon implementation
*/
class MutablePolygon(
override val positions: MutableList<Vector3> = mutableListOf(),
override val normals: MutableList<Vector3> = mutableListOf(),
Expand All @@ -77,7 +84,7 @@ class MutablePolygon(


/**
* Calculates the 3D bounding box of a list of [IPolygon].
* Calculate the 3D bounding box of a list of [IPolygon].
*/
fun bounds(polygons: List<IPolygon>): Box {
var minX = Double.POSITIVE_INFINITY
Expand All @@ -101,3 +108,42 @@ fun bounds(polygons: List<IPolygon>): Box {
}
return Box(Vector3(minX, minY, minZ), maxX - minX, maxY - minY, maxZ - minZ)
}


/**
* Convert list of polygons to [MeshData]
*/
fun List<IPolygon>.toMeshData(): MeshData {
val vertexData = MutableVertexData()

for (p in this) {
vertexData.positions.addAll(p.positions)
vertexData.normals.addAll(p.normals)
vertexData.colors.addAll(p.colors)
vertexData.textureCoords.addAll(p.textureCoords)
vertexData.tangents.addAll(p.tangents)
vertexData.bitangents.addAll(p.bitangents)
}

val indexedPolygons = mutableListOf<IndexedPolygon>()

var vertexOffset = 0
for (p in this) {

val indices = (vertexOffset until vertexOffset + p.positions.size).toList()

indexedPolygons.add(
IndexedPolygon(
positions = indices,
textureCoords = if (p.textureCoords.isNotEmpty()) indices else emptyList(),
normals = if (p.normals.isNotEmpty()) indices else emptyList(),
colors = if (p.colors.isNotEmpty()) indices else emptyList(),
tangents = if (p.tangents.isNotEmpty()) indices else emptyList(),
bitangents = if (p.bitangents.isNotEmpty()) indices else emptyList()
)
)

vertexOffset += p.positions.size
}
return MeshData(vertexData.toVertexData(), indexedPolygons)
}
42 changes: 39 additions & 3 deletions orx-mesh/src/commonMain/kotlin/VertexData.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import org.openrndr.color.ColorRGBa
import org.openrndr.math.Vector2
import org.openrndr.math.Vector3


/**
* Vertex data interface
*/
Expand Down Expand Up @@ -40,20 +39,57 @@ interface IVertexData {
val bitangents: List<Vector3>
}

/**
* Immutable vertex data implementation
*/
class VertexData(
override val positions: List<Vector3> = emptyList(),
override val normals: List<Vector3> = emptyList(),
override val textureCoords: List<Vector2> = emptyList(),
override val colors: List<ColorRGBa> = emptyList(),
override val tangents: List<Vector3> = emptyList(),
override val bitangents: List<Vector3> = emptyList()
) : IVertexData
) : IVertexData {

/**
* Convert to [MutableVertexData]
*/
fun toMutableVertexData(): MutableVertexData {
return MutableVertexData(
positions.toMutableList(),
normals.toMutableList(),
textureCoords.toMutableList(),
colors.toMutableList(),
tangents.toMutableList(),
bitangents.toMutableList()
)
}
}


/**
* Mutable vertex data implementation
*/
class MutableVertexData(
override val positions: MutableList<Vector3> = mutableListOf(),
override val normals: MutableList<Vector3> = mutableListOf(),
override val textureCoords: MutableList<Vector2> = mutableListOf(),
override val colors: MutableList<ColorRGBa> = mutableListOf(),
override val tangents: MutableList<Vector3> = mutableListOf(),
override val bitangents: MutableList<Vector3> = mutableListOf()
) : IVertexData
) : IVertexData {

/**
* Convert to [VertexData]
*/
fun toVertexData(): VertexData {
return VertexData(
positions.toList(),
normals.toList(),
textureCoords.toList(),
colors.toList(),
tangents.toList(),
bitangents.toList()
)
}
}
Loading

0 comments on commit ed55899

Please sign in to comment.