changes
This commit is contained in:
@@ -1,61 +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 = 1.0,
|
||||
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)
|
||||
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 = 1.0,
|
||||
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)
|
||||
}
|
||||
@@ -1,101 +1,101 @@
|
||||
package org.openrndr.extras.meshgenerators
|
||||
|
||||
import org.openrndr.math.Vector2
|
||||
import org.openrndr.math.Vector3
|
||||
import org.openrndr.math.transforms.rotateY
|
||||
|
||||
fun generateCap(sides: Int, radius: Double, enveloppe: List<Vector2> = listOf(Vector2(0.0, 0.0), Vector2(1.0, 0.0)), writer: VertexWriter) {
|
||||
val maxX = enveloppe.maxBy { it.x } ?: Vector2(1.0, 0.0)
|
||||
val a = maxX.x
|
||||
|
||||
val cleanEnveloppe = enveloppe.map { Vector2((it.x / a) * radius, it.y) }
|
||||
|
||||
val normals2D = enveloppe.zipWithNext().map {
|
||||
val d = it.second - it.first
|
||||
d.normalized.perpendicular
|
||||
}
|
||||
|
||||
val basePositions = cleanEnveloppe.map { Vector3(it.x, it.y, 0.0) }
|
||||
val baseNormals = normals2D.map { Vector3(it.x, it.y, 0.0) }
|
||||
|
||||
for (side in 0 until sides) {
|
||||
val r0 = rotateY(360.0 / sides * side)
|
||||
val r1 = rotateY(360.0 / sides * (side + 1))
|
||||
|
||||
val v0 = basePositions.map { (r0 * it.xyz0).xyz }
|
||||
val v1 = basePositions.map { (r1 * it.xyz0).xyz }
|
||||
val n0 = baseNormals.map { (r0 * it.xyz0).xyz }
|
||||
val n1 = baseNormals.map { (r1 * it.xyz0).xyz }
|
||||
|
||||
for (segment in 0 until basePositions.size - 1) {
|
||||
|
||||
val p00 = v0[segment]
|
||||
val p01 = v0[segment+1]
|
||||
val p10 = v1[segment]
|
||||
val p11 = v1[segment+1]
|
||||
|
||||
val nn0 = n0[segment]
|
||||
val nn1 = n1[segment]
|
||||
|
||||
writer(p00, nn0, Vector2.ZERO)
|
||||
writer(p01, nn0, Vector2.ZERO)
|
||||
writer(p11, nn1, Vector2.ZERO)
|
||||
|
||||
writer(p11, nn1, Vector2.ZERO)
|
||||
writer(p10, nn1, Vector2.ZERO)
|
||||
writer(p00, nn0, Vector2.ZERO)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun generateRevolve(sides: Int, length: Double, enveloppe: List<Vector2> = listOf(Vector2(1.0, 0.0), Vector2(1.0, 1.0)), writer: VertexWriter) {
|
||||
val maxY = enveloppe.maxBy { it.y } ?: Vector2(0.0, 1.0)
|
||||
val a = maxY.y
|
||||
|
||||
val cleanEnveloppe = enveloppe.map { Vector2((it.x), (it.y/a - 0.5) * length ) }
|
||||
|
||||
val normals2D = enveloppe.zipWithNext().map {
|
||||
val d = it.second - it.first
|
||||
d.normalized.perpendicular * Vector2(1.0, -1.0)
|
||||
|
||||
}
|
||||
|
||||
val extended = listOf(normals2D[0]) + normals2D + normals2D[normals2D.size-1]
|
||||
|
||||
// extended.zipW
|
||||
|
||||
println(normals2D.joinToString(", "))
|
||||
|
||||
val basePositions = cleanEnveloppe.map { Vector3(it.x, it.y, 0.0) }
|
||||
val baseNormals = normals2D.map { Vector3(it.x, it.y, 0.0) }
|
||||
|
||||
for (side in 0 until sides) {
|
||||
val r0 = rotateY(360.0 / sides * side)
|
||||
val r1 = rotateY(360.0 / sides * (side + 1))
|
||||
|
||||
val v0 = basePositions.map { (r0 * it.xyz0).xyz }
|
||||
val v1 = basePositions.map { (r1 * it.xyz0).xyz }
|
||||
val n0 = baseNormals.map { (r0 * it.xyz0).xyz }
|
||||
val n1 = baseNormals.map { (r1 * it.xyz0).xyz }
|
||||
|
||||
for (segment in 0 until basePositions.size - 1) {
|
||||
|
||||
val p00 = v0[segment]
|
||||
val p01 = v0[segment+1]
|
||||
val p10 = v1[segment]
|
||||
val p11 = v1[segment+1]
|
||||
|
||||
val nn0 = n0[segment]
|
||||
val nn1 = n1[segment]
|
||||
|
||||
writer(p00, nn0, Vector2.ZERO)
|
||||
writer(p10, nn1, Vector2.ZERO)
|
||||
writer(p11, nn1, Vector2.ZERO)
|
||||
|
||||
writer(p11, nn1, Vector2.ZERO)
|
||||
writer(p01, nn0, Vector2.ZERO)
|
||||
|
||||
writer(p00, nn0, Vector2.ZERO)
|
||||
}
|
||||
}
|
||||
package org.openrndr.extras.meshgenerators
|
||||
|
||||
import org.openrndr.math.Vector2
|
||||
import org.openrndr.math.Vector3
|
||||
import org.openrndr.math.transforms.rotateY
|
||||
|
||||
fun generateCap(sides: Int, radius: Double, enveloppe: List<Vector2> = listOf(Vector2(0.0, 0.0), Vector2(1.0, 0.0)), writer: VertexWriter) {
|
||||
val maxX = enveloppe.maxBy { it.x } ?: Vector2(1.0, 0.0)
|
||||
val a = maxX.x
|
||||
|
||||
val cleanEnveloppe = enveloppe.map { Vector2((it.x / a) * radius, it.y) }
|
||||
|
||||
val normals2D = enveloppe.zipWithNext().map {
|
||||
val d = it.second - it.first
|
||||
d.normalized.perpendicular
|
||||
}
|
||||
|
||||
val basePositions = cleanEnveloppe.map { Vector3(it.x, it.y, 0.0) }
|
||||
val baseNormals = normals2D.map { Vector3(it.x, it.y, 0.0) }
|
||||
|
||||
for (side in 0 until sides) {
|
||||
val r0 = rotateY(360.0 / sides * side)
|
||||
val r1 = rotateY(360.0 / sides * (side + 1))
|
||||
|
||||
val v0 = basePositions.map { (r0 * it.xyz0).xyz }
|
||||
val v1 = basePositions.map { (r1 * it.xyz0).xyz }
|
||||
val n0 = baseNormals.map { (r0 * it.xyz0).xyz }
|
||||
val n1 = baseNormals.map { (r1 * it.xyz0).xyz }
|
||||
|
||||
for (segment in 0 until basePositions.size - 1) {
|
||||
|
||||
val p00 = v0[segment]
|
||||
val p01 = v0[segment+1]
|
||||
val p10 = v1[segment]
|
||||
val p11 = v1[segment+1]
|
||||
|
||||
val nn0 = n0[segment]
|
||||
val nn1 = n1[segment]
|
||||
|
||||
writer(p00, nn0, Vector2.ZERO)
|
||||
writer(p01, nn0, Vector2.ZERO)
|
||||
writer(p11, nn1, Vector2.ZERO)
|
||||
|
||||
writer(p11, nn1, Vector2.ZERO)
|
||||
writer(p10, nn1, Vector2.ZERO)
|
||||
writer(p00, nn0, Vector2.ZERO)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun generateRevolve(sides: Int, length: Double, enveloppe: List<Vector2> = listOf(Vector2(1.0, 0.0), Vector2(1.0, 1.0)), writer: VertexWriter) {
|
||||
val maxY = enveloppe.maxBy { it.y } ?: Vector2(0.0, 1.0)
|
||||
val a = maxY.y
|
||||
|
||||
val cleanEnveloppe = enveloppe.map { Vector2((it.x), (it.y/a - 0.5) * length ) }
|
||||
|
||||
val normals2D = enveloppe.zipWithNext().map {
|
||||
val d = it.second - it.first
|
||||
d.normalized.perpendicular * Vector2(1.0, -1.0)
|
||||
|
||||
}
|
||||
|
||||
val extended = listOf(normals2D[0]) + normals2D + normals2D[normals2D.size-1]
|
||||
|
||||
// extended.zipW
|
||||
|
||||
println(normals2D.joinToString(", "))
|
||||
|
||||
val basePositions = cleanEnveloppe.map { Vector3(it.x, it.y, 0.0) }
|
||||
val baseNormals = normals2D.map { Vector3(it.x, it.y, 0.0) }
|
||||
|
||||
for (side in 0 until sides) {
|
||||
val r0 = rotateY(360.0 / sides * side)
|
||||
val r1 = rotateY(360.0 / sides * (side + 1))
|
||||
|
||||
val v0 = basePositions.map { (r0 * it.xyz0).xyz }
|
||||
val v1 = basePositions.map { (r1 * it.xyz0).xyz }
|
||||
val n0 = baseNormals.map { (r0 * it.xyz0).xyz }
|
||||
val n1 = baseNormals.map { (r1 * it.xyz0).xyz }
|
||||
|
||||
for (segment in 0 until basePositions.size - 1) {
|
||||
|
||||
val p00 = v0[segment]
|
||||
val p01 = v0[segment+1]
|
||||
val p10 = v1[segment]
|
||||
val p11 = v1[segment+1]
|
||||
|
||||
val nn0 = n0[segment]
|
||||
val nn1 = n1[segment]
|
||||
|
||||
writer(p00, nn0, Vector2.ZERO)
|
||||
writer(p10, nn1, Vector2.ZERO)
|
||||
writer(p11, nn1, Vector2.ZERO)
|
||||
|
||||
writer(p11, nn1, Vector2.ZERO)
|
||||
writer(p01, nn0, Vector2.ZERO)
|
||||
|
||||
writer(p00, nn0, Vector2.ZERO)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,82 +1,82 @@
|
||||
package org.openrndr.extras.meshgenerators
|
||||
|
||||
import org.openrndr.draw.VertexBuffer
|
||||
import org.openrndr.math.Vector2
|
||||
import org.openrndr.math.Vector3
|
||||
import org.openrndr.math.mix
|
||||
import org.openrndr.math.transforms.rotateZ
|
||||
|
||||
fun cylinderMesh(sides: Int = 16, segments: Int = 16, radius: Double = 1.0, length: Double, invert: Boolean = false): VertexBuffer {
|
||||
val vertexCount = 6 * sides * segments
|
||||
val vb = meshVertexBuffer(vertexCount)
|
||||
vb.put {
|
||||
generateCylinder(sides, segments, radius, length, invert, bufferWriter(this))
|
||||
}
|
||||
return vb
|
||||
}
|
||||
|
||||
fun generateCylinder(sides: Int, segments: Int, radius: Double, length: Double, invert: Boolean = false, vertexWriter: VertexWriter) {
|
||||
return generateTaperedCylinder(sides, segments, radius, radius, length, invert, vertexWriter)
|
||||
}
|
||||
|
||||
fun generateTaperedCylinder(sides: Int, segments: Int, radiusStart: Double, radiusEnd:Double, length: Double, invert: Boolean = false, vertexWriter: VertexWriter) {
|
||||
val dphi = (Math.PI * 2) / sides
|
||||
val ddeg = (360.0) / sides
|
||||
|
||||
val invertFactor = if (invert) -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 baseNormal = Vector3(1.0, 0.0, 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 - length/2.0
|
||||
val z1 = (length / segments) * (segment + 1) - length/2.0
|
||||
|
||||
|
||||
for (side in 0 until sides) {
|
||||
val x00 = Math.cos(side * dphi) * radius0
|
||||
val x10 = Math.cos(side * dphi + dphi) * radius0
|
||||
val y00 = Math.sin(side * dphi) * radius0
|
||||
val y10 = Math.sin(side * dphi + dphi) * radius0
|
||||
|
||||
val x01 = Math.cos(side * dphi) * radius1
|
||||
val x11 = Math.cos(side * dphi + dphi) * radius1
|
||||
val y01 = Math.sin(side * dphi) * radius1
|
||||
val y11 = Math.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 = (rotateZ(side * ddeg) * baseNormal.xyz0).xyz.normalized * invertFactor
|
||||
val n1 = (rotateZ((side+1) * ddeg) * baseNormal.xyz0).xyz.normalized * invertFactor
|
||||
|
||||
|
||||
if (!invert) {
|
||||
vertexWriter(Vector3(x00, y00, z0), n0, Vector2(u0, v0))
|
||||
vertexWriter(Vector3(x10, y10, z0), n1, Vector2(u0, v1))
|
||||
vertexWriter(Vector3(x11, y11, z1), n1, Vector2(u1, v1))
|
||||
|
||||
vertexWriter(Vector3(x11, y11, z1), n1, Vector2(u1, v1))
|
||||
vertexWriter(Vector3(x01, y01, z1), n0, Vector2(u1, v0))
|
||||
vertexWriter(Vector3(x00, y00, z0), n0, Vector2(u0, v0))
|
||||
} else {
|
||||
vertexWriter(Vector3(x00, y00, z0), n0, Vector2(u0, v0))
|
||||
vertexWriter(Vector3(x01, y01, z1), n0, Vector2(u1, v0))
|
||||
vertexWriter(Vector3(x11, y11, z1), n1, Vector2(u1, v1))
|
||||
|
||||
vertexWriter(Vector3(x11, y11, z1), n1, Vector2(u1, v1))
|
||||
vertexWriter(Vector3(x10, y10, z0), n1, Vector2(u0, v1))
|
||||
vertexWriter(Vector3(x00, y00, z0), n0, Vector2(u0, v0))
|
||||
}
|
||||
}
|
||||
}
|
||||
package org.openrndr.extras.meshgenerators
|
||||
|
||||
import org.openrndr.draw.VertexBuffer
|
||||
import org.openrndr.math.Vector2
|
||||
import org.openrndr.math.Vector3
|
||||
import org.openrndr.math.mix
|
||||
import org.openrndr.math.transforms.rotateZ
|
||||
|
||||
fun cylinderMesh(sides: Int = 16, segments: Int = 16, radius: Double = 1.0, length: Double, invert: Boolean = false): VertexBuffer {
|
||||
val vertexCount = 6 * sides * segments
|
||||
val vb = meshVertexBuffer(vertexCount)
|
||||
vb.put {
|
||||
generateCylinder(sides, segments, radius, length, invert, bufferWriter(this))
|
||||
}
|
||||
return vb
|
||||
}
|
||||
|
||||
fun generateCylinder(sides: Int, segments: Int, radius: Double, length: Double, invert: Boolean = false, vertexWriter: VertexWriter) {
|
||||
return generateTaperedCylinder(sides, segments, radius, radius, length, invert, vertexWriter)
|
||||
}
|
||||
|
||||
fun generateTaperedCylinder(sides: Int, segments: Int, radiusStart: Double, radiusEnd:Double, length: Double, invert: Boolean = false, vertexWriter: VertexWriter) {
|
||||
val dphi = (Math.PI * 2) / sides
|
||||
val ddeg = (360.0) / sides
|
||||
|
||||
val invertFactor = if (invert) -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 baseNormal = Vector3(1.0, 0.0, 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 - length/2.0
|
||||
val z1 = (length / segments) * (segment + 1) - length/2.0
|
||||
|
||||
|
||||
for (side in 0 until sides) {
|
||||
val x00 = Math.cos(side * dphi) * radius0
|
||||
val x10 = Math.cos(side * dphi + dphi) * radius0
|
||||
val y00 = Math.sin(side * dphi) * radius0
|
||||
val y10 = Math.sin(side * dphi + dphi) * radius0
|
||||
|
||||
val x01 = Math.cos(side * dphi) * radius1
|
||||
val x11 = Math.cos(side * dphi + dphi) * radius1
|
||||
val y01 = Math.sin(side * dphi) * radius1
|
||||
val y11 = Math.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 = (rotateZ(side * ddeg) * baseNormal.xyz0).xyz.normalized * invertFactor
|
||||
val n1 = (rotateZ((side+1) * ddeg) * baseNormal.xyz0).xyz.normalized * invertFactor
|
||||
|
||||
|
||||
if (!invert) {
|
||||
vertexWriter(Vector3(x00, y00, z0), n0, Vector2(u0, v0))
|
||||
vertexWriter(Vector3(x10, y10, z0), n1, Vector2(u0, v1))
|
||||
vertexWriter(Vector3(x11, y11, z1), n1, Vector2(u1, v1))
|
||||
|
||||
vertexWriter(Vector3(x11, y11, z1), n1, Vector2(u1, v1))
|
||||
vertexWriter(Vector3(x01, y01, z1), n0, Vector2(u1, v0))
|
||||
vertexWriter(Vector3(x00, y00, z0), n0, Vector2(u0, v0))
|
||||
} else {
|
||||
vertexWriter(Vector3(x00, y00, z0), n0, Vector2(u0, v0))
|
||||
vertexWriter(Vector3(x01, y01, z1), n0, Vector2(u1, v0))
|
||||
vertexWriter(Vector3(x11, y11, z1), n1, Vector2(u1, v1))
|
||||
|
||||
vertexWriter(Vector3(x11, y11, z1), n1, Vector2(u1, v1))
|
||||
vertexWriter(Vector3(x10, y10, z0), n1, Vector2(u0, v1))
|
||||
vertexWriter(Vector3(x00, y00, z0), n0, Vector2(u0, v0))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,172 +1,172 @@
|
||||
package org.openrndr.extras.meshgenerators
|
||||
|
||||
import org.openrndr.draw.VertexBuffer
|
||||
import org.openrndr.draw.vertexBuffer
|
||||
import org.openrndr.draw.vertexFormat
|
||||
import org.openrndr.math.Matrix44
|
||||
import org.openrndr.math.Vector2
|
||||
import org.openrndr.math.Vector3
|
||||
import org.openrndr.math.transforms.rotate
|
||||
import org.openrndr.math.transforms.transform
|
||||
import org.openrndr.shape.Shape
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.ByteOrder
|
||||
|
||||
class GeneratorBuffer {
|
||||
class VertexData(val position: Vector3, val normal: Vector3, val texCoord: Vector2)
|
||||
|
||||
var data = mutableListOf<VertexData>()
|
||||
|
||||
fun write(position: Vector3, normal: Vector3, texCoord: Vector2) {
|
||||
data.add(VertexData(position, normal, texCoord))
|
||||
}
|
||||
|
||||
fun concat(other: GeneratorBuffer) {
|
||||
data.addAll(other.data)
|
||||
}
|
||||
|
||||
fun transform(m: Matrix44) {
|
||||
data = data.map {
|
||||
VertexData((m * (it.position.xyz1)).xyz, (m * (it.normal.xyz0)).xyz, it.texCoord)
|
||||
}.toMutableList()
|
||||
}
|
||||
|
||||
fun toByteBuffer(): ByteBuffer {
|
||||
val bb = ByteBuffer.allocateDirect(data.size * (3 * 4 + 3 * 4 + 2 * 4))
|
||||
bb.order(ByteOrder.nativeOrder())
|
||||
bb.rewind()
|
||||
for (d in data) {
|
||||
bb.putFloat(d.position.x.toFloat())
|
||||
bb.putFloat(d.position.y.toFloat())
|
||||
bb.putFloat(d.position.z.toFloat())
|
||||
|
||||
bb.putFloat(d.normal.x.toFloat())
|
||||
bb.putFloat(d.normal.y.toFloat())
|
||||
bb.putFloat(d.normal.z.toFloat())
|
||||
|
||||
bb.putFloat(d.texCoord.x.toFloat())
|
||||
bb.putFloat(d.texCoord.y.toFloat())
|
||||
}
|
||||
return bb
|
||||
}
|
||||
}
|
||||
|
||||
fun GeneratorBuffer.sphere(sides: Int, segments: Int, radius: Double, invert: Boolean = false) {
|
||||
generateSphere(sides, segments, radius, invert, this::write)
|
||||
}
|
||||
|
||||
fun GeneratorBuffer.hemisphere(sides: Int, segments: Int, radius: Double, invert: Boolean = false) {
|
||||
generateHemisphere(sides, segments, radius, invert, this::write)
|
||||
}
|
||||
|
||||
enum class GridCoordinates {
|
||||
INDEX,
|
||||
UNIPOLAR,
|
||||
BIPOLAR,
|
||||
}
|
||||
|
||||
fun GeneratorBuffer.grid(width: Int, height: Int, coordinates: GridCoordinates = GridCoordinates.BIPOLAR, builder: GeneratorBuffer.(u: Double, v: Double) -> Unit) {
|
||||
for (v in 0 until height) {
|
||||
for (u in 0 until width) {
|
||||
group {
|
||||
when (coordinates) {
|
||||
GridCoordinates.INDEX -> this.builder(u * 1.0, v * 1.0)
|
||||
GridCoordinates.BIPOLAR -> this.builder(2 * u / (width - 1.0) - 1,
|
||||
2 * v / (height - 1.0) - 1)
|
||||
GridCoordinates.UNIPOLAR -> this.builder(u / (width - 1.0), v / (height - 1.0))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun GeneratorBuffer.twist(degreesPerUnit: Double, start: Double, axis: Vector3 = Vector3.UNIT_Y) {
|
||||
data = data.map {
|
||||
val p = it.position.projectedOn(axis)
|
||||
val t = if (axis.x != 0.0) p.x / axis.x else if (axis.y != 0.0) p.y / axis.y else if (axis.z != 0.0) p.z / axis.z else
|
||||
throw IllegalArgumentException("0 axis")
|
||||
val r = rotate(axis, t * degreesPerUnit)
|
||||
GeneratorBuffer.VertexData((r * it.position.xyz1).xyz, (r * it.normal.xyz0).xyz, it.texCoord)
|
||||
}.toMutableList()
|
||||
}
|
||||
|
||||
fun GeneratorBuffer.grid(width: Int, height: Int, depth: Int, coordinates: GridCoordinates = GridCoordinates.BIPOLAR, builder: GeneratorBuffer.(u: Double, v: Double, w: Double) -> Unit) {
|
||||
for (w in 0 until depth) {
|
||||
for (v in 0 until height) {
|
||||
for (u in 0 until width) {
|
||||
group {
|
||||
when (coordinates) {
|
||||
GridCoordinates.INDEX -> this.builder(u * 1.0, v * 1.0, w * 1.0)
|
||||
GridCoordinates.BIPOLAR -> this.builder(2 * u / (width - 1.0) - 1,
|
||||
2 * v / (height - 1.0) - 1, 2 * w / (depth - 1.0) - 1)
|
||||
GridCoordinates.UNIPOLAR -> this.builder(u / (width - 1.0), v / (height - 1.0), w / (depth - 1.0))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun GeneratorBuffer.box(width: Double, height: Double, depth: Double, widthSegments: Int = 1, heightSegments: Int = 1, depthSegments: Int = 1, invert: Boolean = false) {
|
||||
generateBox(width, height, depth, widthSegments, heightSegments, depthSegments, invert, this::write)
|
||||
}
|
||||
|
||||
fun GeneratorBuffer.cylinder(sides: Int, segments: Int, radius: Double, length: Double, invert: Boolean = false) {
|
||||
generateCylinder(sides, segments, radius, length, invert, this::write)
|
||||
}
|
||||
|
||||
fun GeneratorBuffer.taperedCylinder(sides: Int, segments: Int, startRadius: Double, endRadius: Double, length: Double, invert: Boolean = false) {
|
||||
generateTaperedCylinder(sides, segments, startRadius, endRadius, length, invert, this::write)
|
||||
}
|
||||
|
||||
fun GeneratorBuffer.cap(sides: Int, radius: Double, enveloppe: List<Vector2>) {
|
||||
generateCap(sides, radius, enveloppe, this::write)
|
||||
}
|
||||
|
||||
fun GeneratorBuffer.revolve(sides:Int, length:Double, enveloppe: List<Vector2>) {
|
||||
generateRevolve(sides, length, enveloppe, this::write)
|
||||
}
|
||||
|
||||
fun GeneratorBuffer.extrudeShape(shape: Shape, length: Double, scale: Double = 1.0, distanceTolerance: Double = 0.5) {
|
||||
extrudeShape(shape, -length / 2.0, length / 2.0, scale, scale, true, true, distanceTolerance, false, this::write)
|
||||
}
|
||||
|
||||
fun meshGenerator(builder: GeneratorBuffer.() -> Unit): VertexBuffer {
|
||||
val gb = GeneratorBuffer()
|
||||
gb.builder()
|
||||
|
||||
val vb = vertexBuffer(vertexFormat {
|
||||
position(3)
|
||||
normal(3)
|
||||
textureCoordinate(2)
|
||||
}, gb.data.size)
|
||||
|
||||
val bb = gb.toByteBuffer()
|
||||
bb.rewind()
|
||||
vb.write(bb)
|
||||
return vb
|
||||
}
|
||||
|
||||
fun generator(builder: GeneratorBuffer.() -> Unit): GeneratorBuffer {
|
||||
val gb = GeneratorBuffer()
|
||||
gb.builder()
|
||||
return gb
|
||||
}
|
||||
|
||||
fun GeneratorBuffer.group(builder: GeneratorBuffer.() -> Unit) {
|
||||
val gb = GeneratorBuffer()
|
||||
gb.builder()
|
||||
this.concat(gb)
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val gb = generator {
|
||||
box(20.0, 20.0, 20.0)
|
||||
group {
|
||||
box(40.0, 40.0, 40.0)
|
||||
transform(transform {
|
||||
translate(0.0, 20.0, 0.0)
|
||||
})
|
||||
}
|
||||
}
|
||||
package org.openrndr.extras.meshgenerators
|
||||
|
||||
import org.openrndr.draw.VertexBuffer
|
||||
import org.openrndr.draw.vertexBuffer
|
||||
import org.openrndr.draw.vertexFormat
|
||||
import org.openrndr.math.Matrix44
|
||||
import org.openrndr.math.Vector2
|
||||
import org.openrndr.math.Vector3
|
||||
import org.openrndr.math.transforms.rotate
|
||||
import org.openrndr.math.transforms.transform
|
||||
import org.openrndr.shape.Shape
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.ByteOrder
|
||||
|
||||
class GeneratorBuffer {
|
||||
class VertexData(val position: Vector3, val normal: Vector3, val texCoord: Vector2)
|
||||
|
||||
var data = mutableListOf<VertexData>()
|
||||
|
||||
fun write(position: Vector3, normal: Vector3, texCoord: Vector2) {
|
||||
data.add(VertexData(position, normal, texCoord))
|
||||
}
|
||||
|
||||
fun concat(other: GeneratorBuffer) {
|
||||
data.addAll(other.data)
|
||||
}
|
||||
|
||||
fun transform(m: Matrix44) {
|
||||
data = data.map {
|
||||
VertexData((m * (it.position.xyz1)).xyz, (m * (it.normal.xyz0)).xyz, it.texCoord)
|
||||
}.toMutableList()
|
||||
}
|
||||
|
||||
fun toByteBuffer(): ByteBuffer {
|
||||
val bb = ByteBuffer.allocateDirect(data.size * (3 * 4 + 3 * 4 + 2 * 4))
|
||||
bb.order(ByteOrder.nativeOrder())
|
||||
bb.rewind()
|
||||
for (d in data) {
|
||||
bb.putFloat(d.position.x.toFloat())
|
||||
bb.putFloat(d.position.y.toFloat())
|
||||
bb.putFloat(d.position.z.toFloat())
|
||||
|
||||
bb.putFloat(d.normal.x.toFloat())
|
||||
bb.putFloat(d.normal.y.toFloat())
|
||||
bb.putFloat(d.normal.z.toFloat())
|
||||
|
||||
bb.putFloat(d.texCoord.x.toFloat())
|
||||
bb.putFloat(d.texCoord.y.toFloat())
|
||||
}
|
||||
return bb
|
||||
}
|
||||
}
|
||||
|
||||
fun GeneratorBuffer.sphere(sides: Int, segments: Int, radius: Double, invert: Boolean = false) {
|
||||
generateSphere(sides, segments, radius, invert, this::write)
|
||||
}
|
||||
|
||||
fun GeneratorBuffer.hemisphere(sides: Int, segments: Int, radius: Double, invert: Boolean = false) {
|
||||
generateHemisphere(sides, segments, radius, invert, this::write)
|
||||
}
|
||||
|
||||
enum class GridCoordinates {
|
||||
INDEX,
|
||||
UNIPOLAR,
|
||||
BIPOLAR,
|
||||
}
|
||||
|
||||
fun GeneratorBuffer.grid(width: Int, height: Int, coordinates: GridCoordinates = GridCoordinates.BIPOLAR, builder: GeneratorBuffer.(u: Double, v: Double) -> Unit) {
|
||||
for (v in 0 until height) {
|
||||
for (u in 0 until width) {
|
||||
group {
|
||||
when (coordinates) {
|
||||
GridCoordinates.INDEX -> this.builder(u * 1.0, v * 1.0)
|
||||
GridCoordinates.BIPOLAR -> this.builder(2 * u / (width - 1.0) - 1,
|
||||
2 * v / (height - 1.0) - 1)
|
||||
GridCoordinates.UNIPOLAR -> this.builder(u / (width - 1.0), v / (height - 1.0))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun GeneratorBuffer.twist(degreesPerUnit: Double, start: Double, axis: Vector3 = Vector3.UNIT_Y) {
|
||||
data = data.map {
|
||||
val p = it.position.projectedOn(axis)
|
||||
val t = if (axis.x != 0.0) p.x / axis.x else if (axis.y != 0.0) p.y / axis.y else if (axis.z != 0.0) p.z / axis.z else
|
||||
throw IllegalArgumentException("0 axis")
|
||||
val r = rotate(axis, t * degreesPerUnit)
|
||||
GeneratorBuffer.VertexData((r * it.position.xyz1).xyz, (r * it.normal.xyz0).xyz, it.texCoord)
|
||||
}.toMutableList()
|
||||
}
|
||||
|
||||
fun GeneratorBuffer.grid(width: Int, height: Int, depth: Int, coordinates: GridCoordinates = GridCoordinates.BIPOLAR, builder: GeneratorBuffer.(u: Double, v: Double, w: Double) -> Unit) {
|
||||
for (w in 0 until depth) {
|
||||
for (v in 0 until height) {
|
||||
for (u in 0 until width) {
|
||||
group {
|
||||
when (coordinates) {
|
||||
GridCoordinates.INDEX -> this.builder(u * 1.0, v * 1.0, w * 1.0)
|
||||
GridCoordinates.BIPOLAR -> this.builder(2 * u / (width - 1.0) - 1,
|
||||
2 * v / (height - 1.0) - 1, 2 * w / (depth - 1.0) - 1)
|
||||
GridCoordinates.UNIPOLAR -> this.builder(u / (width - 1.0), v / (height - 1.0), w / (depth - 1.0))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun GeneratorBuffer.box(width: Double, height: Double, depth: Double, widthSegments: Int = 1, heightSegments: Int = 1, depthSegments: Int = 1, invert: Boolean = false) {
|
||||
generateBox(width, height, depth, widthSegments, heightSegments, depthSegments, invert, this::write)
|
||||
}
|
||||
|
||||
fun GeneratorBuffer.cylinder(sides: Int, segments: Int, radius: Double, length: Double, invert: Boolean = false) {
|
||||
generateCylinder(sides, segments, radius, length, invert, this::write)
|
||||
}
|
||||
|
||||
fun GeneratorBuffer.taperedCylinder(sides: Int, segments: Int, startRadius: Double, endRadius: Double, length: Double, invert: Boolean = false) {
|
||||
generateTaperedCylinder(sides, segments, startRadius, endRadius, length, invert, this::write)
|
||||
}
|
||||
|
||||
fun GeneratorBuffer.cap(sides: Int, radius: Double, enveloppe: List<Vector2>) {
|
||||
generateCap(sides, radius, enveloppe, this::write)
|
||||
}
|
||||
|
||||
fun GeneratorBuffer.revolve(sides:Int, length:Double, enveloppe: List<Vector2>) {
|
||||
generateRevolve(sides, length, enveloppe, this::write)
|
||||
}
|
||||
|
||||
fun GeneratorBuffer.extrudeShape(shape: Shape, length: Double, scale: Double = 1.0, distanceTolerance: Double = 0.5) {
|
||||
extrudeShape(shape, -length / 2.0, length / 2.0, scale, scale, true, true, distanceTolerance, false, this::write)
|
||||
}
|
||||
|
||||
fun meshGenerator(builder: GeneratorBuffer.() -> Unit): VertexBuffer {
|
||||
val gb = GeneratorBuffer()
|
||||
gb.builder()
|
||||
|
||||
val vb = vertexBuffer(vertexFormat {
|
||||
position(3)
|
||||
normal(3)
|
||||
textureCoordinate(2)
|
||||
}, gb.data.size)
|
||||
|
||||
val bb = gb.toByteBuffer()
|
||||
bb.rewind()
|
||||
vb.write(bb)
|
||||
return vb
|
||||
}
|
||||
|
||||
fun generator(builder: GeneratorBuffer.() -> Unit): GeneratorBuffer {
|
||||
val gb = GeneratorBuffer()
|
||||
gb.builder()
|
||||
return gb
|
||||
}
|
||||
|
||||
fun GeneratorBuffer.group(builder: GeneratorBuffer.() -> Unit) {
|
||||
val gb = GeneratorBuffer()
|
||||
gb.builder()
|
||||
this.concat(gb)
|
||||
}
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
val gb = generator {
|
||||
box(20.0, 20.0, 20.0)
|
||||
group {
|
||||
box(40.0, 40.0, 40.0)
|
||||
transform(transform {
|
||||
translate(0.0, 20.0, 0.0)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,84 +1,84 @@
|
||||
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 = 1): VertexBuffer {
|
||||
|
||||
val vertexCount = (widthSegments * heightSegments) * 6
|
||||
val vb = meshVertexBuffer(vertexCount)
|
||||
vb.put {
|
||||
generatePlane(center, right, forward, 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 = 1): VertexBuffer {
|
||||
return planeMesh(Vector3.ZERO, Vector3.UNIT_X, Vector3.UNIT_Z, Vector3.UNIT_Y,
|
||||
width, height, widthSegments, heightSegments)
|
||||
}
|
||||
|
||||
/**
|
||||
* generates a finite plane with its center at (0,0,0) and spanning the xy-plane
|
||||
*/
|
||||
fun wallPlaneMesh(width: Double = 1.0,
|
||||
height: Double = 1.0,
|
||||
widthSegments: Int = 1,
|
||||
heightSegments: Int = 1): VertexBuffer {
|
||||
return planeMesh(Vector3.ZERO, Vector3.UNIT_X, Vector3.UNIT_Y, Vector3.UNIT_Z,
|
||||
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(c11, up, uv00)
|
||||
writer(c10, up, uv10)
|
||||
writer(c00, up, uv11)
|
||||
|
||||
writer(c00, up, uv11)
|
||||
writer(c01, up, uv01)
|
||||
writer(c11, up, uv00)
|
||||
}
|
||||
}
|
||||
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 = 1): VertexBuffer {
|
||||
|
||||
val vertexCount = (widthSegments * heightSegments) * 6
|
||||
val vb = meshVertexBuffer(vertexCount)
|
||||
vb.put {
|
||||
generatePlane(center, right, forward, 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 = 1): VertexBuffer {
|
||||
return planeMesh(Vector3.ZERO, Vector3.UNIT_X, Vector3.UNIT_Z, Vector3.UNIT_Y,
|
||||
width, height, widthSegments, heightSegments)
|
||||
}
|
||||
|
||||
/**
|
||||
* generates a finite plane with its center at (0,0,0) and spanning the xy-plane
|
||||
*/
|
||||
fun wallPlaneMesh(width: Double = 1.0,
|
||||
height: Double = 1.0,
|
||||
widthSegments: Int = 1,
|
||||
heightSegments: Int = 1): VertexBuffer {
|
||||
return planeMesh(Vector3.ZERO, Vector3.UNIT_X, Vector3.UNIT_Y, Vector3.UNIT_Z,
|
||||
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(c11, up, uv00)
|
||||
writer(c10, up, uv10)
|
||||
writer(c00, up, uv11)
|
||||
|
||||
writer(c00, up, uv11)
|
||||
writer(c01, up, uv01)
|
||||
writer(c11, up, uv00)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,84 +1,84 @@
|
||||
package org.openrndr.extras.meshgenerators
|
||||
|
||||
import org.openrndr.draw.VertexBuffer
|
||||
import org.openrndr.math.Spherical
|
||||
import org.openrndr.math.Vector2
|
||||
|
||||
fun sphereMesh(sides: Int = 16, segments: Int = 16, radius: Double = 1.0, invert: Boolean = false): VertexBuffer {
|
||||
val vertexCount = 2 * sides * 3 + Math.max(0, (segments - 2)) * sides * 6
|
||||
val vb = meshVertexBuffer(vertexCount)
|
||||
vb.put {
|
||||
generateSphere(sides, segments, radius, invert, bufferWriter(this))
|
||||
}
|
||||
return vb
|
||||
}
|
||||
|
||||
|
||||
fun generateSphere(sides: Int, segments: Int, radius: Double = 1.0, invert: Boolean = false, writer: VertexWriter) {
|
||||
val inverter = if (invert) -1.0 else 1.0
|
||||
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 * inverter, Vector2(st00.phi / phiMax, st00.theta / thetaMax))
|
||||
writer(st01.cartesian, st01.cartesian.normalized * inverter, Vector2(st01.phi / phiMax, st01.theta / thetaMax))
|
||||
writer(st11.cartesian, st11.cartesian.normalized * inverter, Vector2(st11.phi / phiMax, st11.theta / thetaMax))
|
||||
}
|
||||
segments - 1 -> {
|
||||
writer(st11.cartesian, st11.cartesian.normalized * inverter, Vector2(st11.phi / phiMax, st11.theta / thetaMax))
|
||||
writer(st10.cartesian, st10.cartesian.normalized * inverter, Vector2(st10.phi / phiMax, st10.theta / thetaMax))
|
||||
writer(st00.cartesian, st00.cartesian.normalized * inverter, Vector2(st00.phi / phiMax, st00.theta / thetaMax))
|
||||
}
|
||||
else -> {
|
||||
writer(st00.cartesian, st00.cartesian.normalized * inverter, Vector2(st00.phi / phiMax, st00.theta / thetaMax))
|
||||
writer(st01.cartesian, st01.cartesian.normalized * inverter, Vector2(st01.phi / phiMax, st01.theta / thetaMax))
|
||||
writer(st11.cartesian, st11.cartesian.normalized * inverter, Vector2(st11.phi / phiMax, st11.theta / thetaMax))
|
||||
|
||||
writer(st11.cartesian, st11.cartesian.normalized * inverter, Vector2(st11.phi / phiMax, st11.theta / thetaMax))
|
||||
writer(st10.cartesian, st10.cartesian.normalized * inverter, Vector2(st10.phi / phiMax, st10.theta / thetaMax))
|
||||
writer(st00.cartesian, st00.cartesian.normalized * inverter, Vector2(st00.phi / phiMax, st00.theta / thetaMax))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun generateHemisphere(sides: Int, segments: Int, radius: Double = 1.0, invert: Boolean = false, writer: VertexWriter) {
|
||||
val inverter = if (invert) -1.0 else 1.0
|
||||
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*0.5 / segments)
|
||||
val st01 = Spherical(radius, s * Math.PI * 2.0 / sides, (t + 1) * Math.PI*0.5 / segments)
|
||||
val st10 = Spherical(radius, (s + 1) * Math.PI * 2.0 / sides, t * Math.PI*0.5 / segments)
|
||||
val st11 = Spherical(radius, (s + 1) * Math.PI * 2.0 / sides, (t + 1) * Math.PI*0.5 / segments)
|
||||
|
||||
val thetaMax = Math.PI * 0.5
|
||||
val phiMax = Math.PI * 2.0
|
||||
|
||||
when (t) {
|
||||
0 -> {
|
||||
writer(st00.cartesian, st00.cartesian.normalized * inverter, Vector2(st00.phi / phiMax, st00.theta / thetaMax))
|
||||
writer(st01.cartesian, st01.cartesian.normalized * inverter, Vector2(st01.phi / phiMax, st01.theta / thetaMax))
|
||||
writer(st11.cartesian, st11.cartesian.normalized * inverter, Vector2(st11.phi / phiMax, st11.theta / thetaMax))
|
||||
}
|
||||
else -> {
|
||||
writer(st00.cartesian, st00.cartesian.normalized * inverter, Vector2(st00.phi / phiMax, st00.theta / thetaMax))
|
||||
writer(st01.cartesian, st01.cartesian.normalized * inverter, Vector2(st01.phi / phiMax, st01.theta / thetaMax))
|
||||
writer(st11.cartesian, st11.cartesian.normalized * inverter, Vector2(st11.phi / phiMax, st11.theta / thetaMax))
|
||||
|
||||
writer(st11.cartesian, st11.cartesian.normalized * inverter, Vector2(st11.phi / phiMax, st11.theta / thetaMax))
|
||||
writer(st10.cartesian, st10.cartesian.normalized * inverter, Vector2(st10.phi / phiMax, st10.theta / thetaMax))
|
||||
writer(st00.cartesian, st00.cartesian.normalized * inverter, Vector2(st00.phi / phiMax, st00.theta / thetaMax))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
package org.openrndr.extras.meshgenerators
|
||||
|
||||
import org.openrndr.draw.VertexBuffer
|
||||
import org.openrndr.math.Spherical
|
||||
import org.openrndr.math.Vector2
|
||||
|
||||
fun sphereMesh(sides: Int = 16, segments: Int = 16, radius: Double = 1.0, invert: Boolean = false): VertexBuffer {
|
||||
val vertexCount = 2 * sides * 3 + Math.max(0, (segments - 2)) * sides * 6
|
||||
val vb = meshVertexBuffer(vertexCount)
|
||||
vb.put {
|
||||
generateSphere(sides, segments, radius, invert, bufferWriter(this))
|
||||
}
|
||||
return vb
|
||||
}
|
||||
|
||||
|
||||
fun generateSphere(sides: Int, segments: Int, radius: Double = 1.0, invert: Boolean = false, writer: VertexWriter) {
|
||||
val inverter = if (invert) -1.0 else 1.0
|
||||
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 * inverter, Vector2(st00.phi / phiMax, st00.theta / thetaMax))
|
||||
writer(st01.cartesian, st01.cartesian.normalized * inverter, Vector2(st01.phi / phiMax, st01.theta / thetaMax))
|
||||
writer(st11.cartesian, st11.cartesian.normalized * inverter, Vector2(st11.phi / phiMax, st11.theta / thetaMax))
|
||||
}
|
||||
segments - 1 -> {
|
||||
writer(st11.cartesian, st11.cartesian.normalized * inverter, Vector2(st11.phi / phiMax, st11.theta / thetaMax))
|
||||
writer(st10.cartesian, st10.cartesian.normalized * inverter, Vector2(st10.phi / phiMax, st10.theta / thetaMax))
|
||||
writer(st00.cartesian, st00.cartesian.normalized * inverter, Vector2(st00.phi / phiMax, st00.theta / thetaMax))
|
||||
}
|
||||
else -> {
|
||||
writer(st00.cartesian, st00.cartesian.normalized * inverter, Vector2(st00.phi / phiMax, st00.theta / thetaMax))
|
||||
writer(st01.cartesian, st01.cartesian.normalized * inverter, Vector2(st01.phi / phiMax, st01.theta / thetaMax))
|
||||
writer(st11.cartesian, st11.cartesian.normalized * inverter, Vector2(st11.phi / phiMax, st11.theta / thetaMax))
|
||||
|
||||
writer(st11.cartesian, st11.cartesian.normalized * inverter, Vector2(st11.phi / phiMax, st11.theta / thetaMax))
|
||||
writer(st10.cartesian, st10.cartesian.normalized * inverter, Vector2(st10.phi / phiMax, st10.theta / thetaMax))
|
||||
writer(st00.cartesian, st00.cartesian.normalized * inverter, Vector2(st00.phi / phiMax, st00.theta / thetaMax))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun generateHemisphere(sides: Int, segments: Int, radius: Double = 1.0, invert: Boolean = false, writer: VertexWriter) {
|
||||
val inverter = if (invert) -1.0 else 1.0
|
||||
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*0.5 / segments)
|
||||
val st01 = Spherical(radius, s * Math.PI * 2.0 / sides, (t + 1) * Math.PI*0.5 / segments)
|
||||
val st10 = Spherical(radius, (s + 1) * Math.PI * 2.0 / sides, t * Math.PI*0.5 / segments)
|
||||
val st11 = Spherical(radius, (s + 1) * Math.PI * 2.0 / sides, (t + 1) * Math.PI*0.5 / segments)
|
||||
|
||||
val thetaMax = Math.PI * 0.5
|
||||
val phiMax = Math.PI * 2.0
|
||||
|
||||
when (t) {
|
||||
0 -> {
|
||||
writer(st00.cartesian, st00.cartesian.normalized * inverter, Vector2(st00.phi / phiMax, st00.theta / thetaMax))
|
||||
writer(st01.cartesian, st01.cartesian.normalized * inverter, Vector2(st01.phi / phiMax, st01.theta / thetaMax))
|
||||
writer(st11.cartesian, st11.cartesian.normalized * inverter, Vector2(st11.phi / phiMax, st11.theta / thetaMax))
|
||||
}
|
||||
else -> {
|
||||
writer(st00.cartesian, st00.cartesian.normalized * inverter, Vector2(st00.phi / phiMax, st00.theta / thetaMax))
|
||||
writer(st01.cartesian, st01.cartesian.normalized * inverter, Vector2(st01.phi / phiMax, st01.theta / thetaMax))
|
||||
writer(st11.cartesian, st11.cartesian.normalized * inverter, Vector2(st11.phi / phiMax, st11.theta / thetaMax))
|
||||
|
||||
writer(st11.cartesian, st11.cartesian.normalized * inverter, Vector2(st11.phi / phiMax, st11.theta / thetaMax))
|
||||
writer(st10.cartesian, st10.cartesian.normalized * inverter, Vector2(st10.phi / phiMax, st10.theta / thetaMax))
|
||||
writer(st00.cartesian, st00.cartesian.normalized * inverter, Vector2(st00.phi / phiMax, st00.theta / thetaMax))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user