diff --git a/.gitignore b/.gitignore index 294641de..4f714a0a 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +.idea/ .gradle/ out/ target/ diff --git a/orx-mesh-generators/src/main/kotlin/Box.kt b/orx-mesh-generators/src/main/kotlin/Box.kt new file mode 100644 index 00000000..e60bb2fb --- /dev/null +++ b/orx-mesh-generators/src/main/kotlin/Box.kt @@ -0,0 +1,61 @@ +package org.openrndr.extras.meshgenerators + +import org.openrndr.draw.VertexBuffer +import org.openrndr.math.Vector3 + +fun boxMesh(width: Double = 1.0, height: Double = 1.0, depth: Double, + widthSegments: Int = 1, heightSegments: Int = 1, depthSegments: Int = 1, + invert: Boolean = false): VertexBuffer { + val vb = meshVertexBuffer(widthSegments * heightSegments * 6 * 2 + + widthSegments * depthSegments * 6 * 2 + + heightSegments * depthSegments * 6 * 2) + vb.put { + generateBox(width, height, depth, + widthSegments, heightSegments, depthSegments, + invert, bufferWriter(this)) + } + return vb +} + +fun generateBox(width: Double = 1.0, height: Double = 1.0, depth: Double = 1.0, + widthSegments: Int = 1, heightSegments: Int = 1, depthSegments: Int = 1, + invert: Boolean = false, + writer: VertexWriter) { + + val sign = if (invert) -1.0 else 1.0 + // +x -- ZY + generatePlane(Vector3(width / 2.0 * sign, 0.0, 0.0), + Vector3.UNIT_Z, Vector3.UNIT_Y, Vector3.UNIT_X, + depth, height, + depthSegments, heightSegments, writer) + + // -x -- ZY + generatePlane(Vector3(-width / 2.0 * sign, 0.0, 0.0), + Vector3.UNIT_Z, Vector3.UNIT_Y, -Vector3.UNIT_X, + depth, height, + depthSegments, heightSegments, writer) + + // +y -- XZ + generatePlane(Vector3(0.0, height / 2.0 * sign, 0.0), + Vector3.UNIT_X, Vector3.UNIT_Z, Vector3.UNIT_Y, + width, depth, + widthSegments, depthSegments, writer) + + // -y -- XZ + generatePlane(Vector3(0.0, -height / 2.0 * sign, 0.0), + Vector3.UNIT_X, Vector3.UNIT_Z, -Vector3.UNIT_Y, + width, depth, + widthSegments, depthSegments, writer) + + // +z -- XY + generatePlane(Vector3(0.0, 0.0, depth / 2.0 * sign), + Vector3.UNIT_X, Vector3.UNIT_Y, Vector3.UNIT_Z, + width, height, + widthSegments, heightSegments, writer) + + // -z -- XY + generatePlane(Vector3(0.0, 0.0, -depth / 2.0 * sign), + Vector3.UNIT_X, Vector3.UNIT_Y, -Vector3.UNIT_Z, + width, height, + widthSegments, heightSegments, writer) +} \ No newline at end of file diff --git a/orx-mesh-generators/src/main/kotlin/Plane.kt b/orx-mesh-generators/src/main/kotlin/Plane.kt new file mode 100644 index 00000000..f15a24d5 --- /dev/null +++ b/orx-mesh-generators/src/main/kotlin/Plane.kt @@ -0,0 +1,72 @@ +package org.openrndr.extras.meshgenerators + +import org.openrndr.draw.VertexBuffer +import org.openrndr.math.Vector2 +import org.openrndr.math.Vector3 + +fun planeMesh(center: Vector3, + right: Vector3, + forward: Vector3, + up: Vector3 = forward.cross(right).normalized, + width: Double = 1.0, height: Double = 1.0, + widthSegments: Int = 1, heightSegments: Int = 2): VertexBuffer { + + val vertexCount = (widthSegments * heightSegments) * 6 + val vb = meshVertexBuffer(vertexCount) + vb.put { + generatePlane(center, forward, right, up, + width, height, widthSegments, heightSegments, bufferWriter(this)) + } + return vb +} + +/** + * generates a finite plane with its center at (0,0,0) and spanning the xz-plane + */ +fun groundPlaneMesh(width: Double = 1.0, + height: Double = 1.0, + widthSegments: Int = 1, + heightSegments: Int): VertexBuffer { + return planeMesh(Vector3.ZERO, Vector3.UNIT_X, Vector3.UNIT_Z, Vector3.UNIT_Y, + width, height, widthSegments, heightSegments) +} + +fun generatePlane(center: Vector3, + right: Vector3, + forward: Vector3, + up: Vector3 = forward.cross(right).normalized, + + width: Double = 1.0, height: Double = 1.0, + widthSegments: Int = 1, heightSegments: Int = 2, + writer: VertexWriter) { + + val forwardStep = forward.normalized * (height / heightSegments) + val rightStep = right.normalized * (width / widthSegments) + + val corner = center - forward.normalized * (height*0.5) - right.normalized * (width * 0.5) + + val step = Vector2(1.0 / width, 1.0 / height) + + for (v in 0 until heightSegments) { + for (u in 0 until widthSegments) { + + val uv00 = Vector2(u + 0.0, v + 0.0) * step + val uv01 = Vector2(u + 0.0, v + 0.1) * step + val uv10 = Vector2(u + 1.0, v + 0.0) * step + val uv11 = Vector2(u + 1.0, v + 0.1) * step + + val c00 = corner + forwardStep * v.toDouble() + rightStep * u.toDouble() + val c01 = corner + forwardStep * (v + 1).toDouble() + rightStep * u.toDouble() + val c10 = corner + forwardStep * v.toDouble() + rightStep * (u + 1).toDouble() + val c11 = corner + forwardStep * (v + 1).toDouble() + rightStep * (u + 1).toDouble() + + writer(c00, up, uv00) + writer(c10, up, uv10) + writer(c11, up, uv11) + + writer(c11, up, uv11) + writer(c01, up, uv01) + writer(c00, up, uv00) + } + } +} \ No newline at end of file diff --git a/orx-mesh-generators/src/main/kotlin/Sphere.kt b/orx-mesh-generators/src/main/kotlin/Sphere.kt new file mode 100644 index 00000000..e83c9b1f --- /dev/null +++ b/orx-mesh-generators/src/main/kotlin/Sphere.kt @@ -0,0 +1,50 @@ +package org.openrndr.extras.meshgenerators + +import org.openrndr.draw.VertexBuffer +import org.openrndr.math.Spherical +import org.openrndr.math.Vector2 + +fun sphereMesh(sides:Int, segments:Int, radius: Double): VertexBuffer { + val vertexCount = 2 * sides * 3 + Math.max(0, (segments-2)) * sides * 6 + val vb = meshVertexBuffer(vertexCount) + vb.put { + generateSphere(sides, segments, radius, bufferWriter(this)) + } + return vb +} + +fun generateSphere(sides: Int, segments: Int, radius: Double = 1.0, writer: VertexWriter) { + for (t in 0 until segments) { + for (s in 0 until sides) { + val st00 = Spherical(radius, s*Math.PI*2.0/sides, t*Math.PI/segments) + val st01 = Spherical(radius, s*Math.PI*2.0/sides, (t+1)*Math.PI/segments) + val st10 = Spherical(radius, (s+1)*Math.PI*2.0/sides, t*Math.PI/segments) + val st11 = Spherical(radius, (s+1)*Math.PI*2.0/sides, (t+1)*Math.PI/segments) + + val thetaMax = Math.PI + val phiMax = Math.PI*2.0 + + when (t) { + 0 -> { + writer(st00.cartesian, st00.cartesian.normalized, Vector2(st00.phi/phiMax, st00.theta/thetaMax)) + writer(st01.cartesian, st01.cartesian.normalized, Vector2(st01.phi/phiMax, st01.theta/thetaMax)) + writer(st11.cartesian, st11.cartesian.normalized, Vector2(st11.phi/phiMax, st11.theta/thetaMax)) + } + segments-1 -> { + writer(st00.cartesian, st00.cartesian.normalized, Vector2(st00.phi/phiMax, st00.theta/thetaMax)) + writer(st10.cartesian, st10.cartesian.normalized, Vector2(st10.phi/phiMax, st10.theta/thetaMax)) + writer(st11.cartesian, st11.cartesian.normalized, Vector2(st11.phi/phiMax, st11.theta/thetaMax)) + } + else -> { + writer(st00.cartesian, st00.cartesian.normalized, Vector2(st00.phi/phiMax, st00.theta/thetaMax)) + writer(st10.cartesian, st10.cartesian.normalized, Vector2(st10.phi/phiMax, st10.theta/thetaMax)) + writer(st11.cartesian, st11.cartesian.normalized, Vector2(st11.phi/phiMax, st11.theta/thetaMax)) + + writer(st11.cartesian, st11.cartesian.normalized, Vector2(st11.phi/phiMax, st11.theta/thetaMax)) + writer(st01.cartesian, st01.cartesian.normalized, Vector2(st01.phi/phiMax, st01.theta/thetaMax)) + writer(st00.cartesian, st00.cartesian.normalized, Vector2(st00.phi/phiMax, st00.theta/thetaMax)) + } + } + } + } +} \ No newline at end of file