141 lines
4.9 KiB
Kotlin
141 lines
4.9 KiB
Kotlin
package org.openrndr.extra.meshgenerators
|
|
|
|
import org.openrndr.draw.VertexBuffer
|
|
import org.openrndr.math.Matrix44
|
|
import org.openrndr.math.Vector2
|
|
import org.openrndr.math.Vector3
|
|
import org.openrndr.math.mix
|
|
import org.openrndr.math.transforms.rotateZ
|
|
import kotlin.math.PI
|
|
import kotlin.math.cos
|
|
import kotlin.math.sin
|
|
|
|
/**
|
|
* Creates a cylinder along the z-axis
|
|
*
|
|
* @param sides the number of sides of the cylinder
|
|
* @param segments the number of segments along the z-axis
|
|
* @param radius the radius of the cylinder
|
|
* @param length the length of the cylinder
|
|
* @param flipNormals generates inside-out geometry if true
|
|
* @param center center the cylinder on the z-plane
|
|
* @return A vertex buffer containing the triangles to render the 3D shape
|
|
*/
|
|
fun cylinderMesh(
|
|
sides: Int = 16,
|
|
segments: Int = 16,
|
|
radius: Double = 1.0,
|
|
length: Double,
|
|
flipNormals: Boolean = false,
|
|
center: Boolean = false,
|
|
): VertexBuffer {
|
|
val vertexCount = 6 * sides * segments
|
|
val vb = meshVertexBuffer(vertexCount)
|
|
vb.put {
|
|
generateCylinder(sides, segments, radius, length, flipNormals, center, bufferWriter(this))
|
|
}
|
|
return vb
|
|
}
|
|
|
|
/**
|
|
* Generate a cylinder along the z-axis
|
|
* @param sides the number of sides of the cylinder
|
|
* @param segments the number of segments along the z-axis
|
|
* @param radius the radius of the cylinder
|
|
* @param length the length of the cylinder
|
|
* @param flipNormals generates inside-out geometry if true
|
|
* @param center centers the cylinder on the z-plane if true
|
|
* @param writer the vertex writer function
|
|
*/
|
|
fun generateCylinder(
|
|
sides: Int,
|
|
segments: Int,
|
|
radius: Double,
|
|
length: Double,
|
|
flipNormals: Boolean = false,
|
|
center: Boolean = false,
|
|
writer: VertexWriter
|
|
) = generateTaperedCylinder(sides, segments, radius, radius, length, flipNormals, center, writer)
|
|
|
|
/**
|
|
* Generate a tapered cylinder along the z-axis
|
|
* @param sides the number of sides of the tapered cylinder
|
|
* @param segments the number of segments along the z-axis
|
|
* @param radiusStart the start radius of the tapered cylinder
|
|
* @param radiusEnd the end radius of the tapered cylinder
|
|
* @param length the length of the tapered cylinder
|
|
* @param flipNormals generates inside-out geometry if true
|
|
* @param center centers the cylinder on the z-plane if true
|
|
* @param writer the vertex writer function
|
|
*/
|
|
fun generateTaperedCylinder(
|
|
sides: Int,
|
|
segments: Int,
|
|
radiusStart: Double,
|
|
radiusEnd: Double,
|
|
length: Double,
|
|
flipNormals: Boolean = false,
|
|
center: Boolean = false,
|
|
writer: VertexWriter
|
|
) {
|
|
val dphi = (PI * 2) / sides
|
|
val ddeg = (360.0) / sides
|
|
|
|
val invertFactor = if (flipNormals) 1.0 else -1.0
|
|
|
|
val dr = radiusEnd - radiusStart
|
|
|
|
val baseNormal = Vector2(length, dr).normalized.perpendicular().let { Vector3(x = it.y, y = 0.0, z = it.x) }
|
|
|
|
val zOffset = if (center) -length / 2.0 else 0.0
|
|
|
|
|
|
for (segment in 0 until segments) {
|
|
val radius0 = mix(radiusStart, radiusEnd, segment * 1.0 / segments)
|
|
val radius1 = mix(radiusStart, radiusEnd, (segment + 1) * 1.0 / segments)
|
|
val z0 = (length / segments) * segment + zOffset
|
|
val z1 = (length / segments) * (segment + 1) + zOffset
|
|
|
|
|
|
for (side in 0 until sides) {
|
|
val x00 = cos(side * dphi) * radius0
|
|
val x10 = cos(side * dphi + dphi) * radius0
|
|
val y00 = sin(side * dphi) * radius0
|
|
val y10 = sin(side * dphi + dphi) * radius0
|
|
|
|
val x01 = cos(side * dphi) * radius1
|
|
val x11 = cos(side * dphi + dphi) * radius1
|
|
val y01 = sin(side * dphi) * radius1
|
|
val y11 = sin(side * dphi + dphi) * radius1
|
|
|
|
|
|
val u0 = (segment + 0.0) / segments
|
|
val u1 = (segment + 1.0) / segments
|
|
val v0 = (side + 0.0) / sides
|
|
val v1 = (side + 1.0) / sides
|
|
|
|
|
|
val n0 = (Matrix44.rotateZ(side * ddeg) * baseNormal.xyz0).xyz.normalized * invertFactor
|
|
val n1 = (Matrix44.rotateZ((side + 1) * ddeg) * baseNormal.xyz0).xyz.normalized * invertFactor
|
|
|
|
|
|
if (flipNormals) {
|
|
writer(Vector3(x00, y00, z0), n0, Vector2(u0, v0))
|
|
writer(Vector3(x10, y10, z0), n1, Vector2(u0, v1))
|
|
writer(Vector3(x11, y11, z1), n1, Vector2(u1, v1))
|
|
|
|
writer(Vector3(x11, y11, z1), n1, Vector2(u1, v1))
|
|
writer(Vector3(x01, y01, z1), n0, Vector2(u1, v0))
|
|
writer(Vector3(x00, y00, z0), n0, Vector2(u0, v0))
|
|
} else {
|
|
writer(Vector3(x00, y00, z0), n0, Vector2(u0, v0))
|
|
writer(Vector3(x01, y01, z1), n0, Vector2(u1, v0))
|
|
writer(Vector3(x11, y11, z1), n1, Vector2(u1, v1))
|
|
|
|
writer(Vector3(x11, y11, z1), n1, Vector2(u1, v1))
|
|
writer(Vector3(x10, y10, z0), n1, Vector2(u0, v1))
|
|
writer(Vector3(x00, y00, z0), n0, Vector2(u0, v0))
|
|
}
|
|
}
|
|
}
|
|
} |