Created
September 12, 2022 17:01
-
-
Save ThomasGorisse/7e07681e6aae794982ced3bc61af7f8d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package io.github.sceneview.geometries | |
import com.google.android.filament.Engine | |
import dev.romainguy.kotlin.math.TWO_PI | |
import dev.romainguy.kotlin.math.normalize | |
import io.github.sceneview.math.Direction | |
import io.github.sceneview.math.Position | |
import io.github.sceneview.math.Size | |
import kotlin.math.cos | |
import kotlin.math.sin | |
/** | |
* Creates a [Geometry] in the shape of a cylinder with the give specifications. | |
* | |
* @param radius the radius of the constructed cylinder | |
* @param height the height of the constructed cylinder | |
* @param center the center of the constructed cylinder | |
*/ | |
class Cylinder( | |
engine: Engine, | |
radius: Float, | |
height: Float, | |
center: Position, | |
sideCount: Int = 24 | |
) : Geometry( | |
engine = engine, | |
vertices = mutableListOf<Vertex>().apply { | |
val halfHeight = height / 2 | |
val thetaIncrement = TWO_PI / sideCount | |
var theta = 0f | |
val uStep = 1.0f / sideCount | |
val lowerCapVertices = mutableListOf<Vertex>() | |
val upperCapVertices = mutableListOf<Vertex>() | |
val upperEdgeVertices = mutableListOf<Vertex>() | |
// Generate vertices along the sides of the cylinder | |
for (side in 0..sideCount) { | |
// Calculate edge vertices along bottom of cylinder | |
var lowerPosition = Position( | |
x = radius * cos(theta), y = -halfHeight, z = radius * sin(theta) | |
) | |
lowerPosition += center | |
add( | |
Vertex( | |
position = lowerPosition, | |
normal = normalize( | |
Direction(x = lowerPosition.x, y = 0.0f, z = lowerPosition.z) | |
), | |
uvCoordinate = UvCoordinate(x = uStep * side, y = 0.0f) | |
) | |
) | |
// Create a copy of lower vertex with bottom-facing normals for cap | |
lowerCapVertices.add( | |
Vertex( | |
position = lowerPosition, | |
normal = Direction(y = -1.0f), | |
uvCoordinate = UvCoordinate(x = uStep * side, y = 0.0f) | |
) | |
) | |
// Calculate edge vertices along top of cylinder | |
var upperPosition = Position( | |
x = radius * cos(theta), y = halfHeight, z = radius * sin(theta) | |
) | |
upperPosition += center | |
upperEdgeVertices.add( | |
Vertex( | |
position = upperPosition, | |
normal = normalize( | |
Direction( | |
x = upperPosition.x, | |
y = 0.0f, | |
z = upperPosition.z | |
) | |
), | |
uvCoordinate = UvCoordinate(x = uStep * side, y = 1.0f) | |
) | |
) | |
// Create a copy of upper vertex with up-facing normals for cap | |
upperCapVertices.add( | |
Vertex( | |
position = upperPosition, | |
normal = Direction(y = 1.0f), | |
uvCoordinate = UvCoordinate( | |
x = (cos(theta) + 1.0f) / 2.0f, y = (sin(theta) + 1.0f) / 2.0f | |
) | |
) | |
) | |
theta += thetaIncrement | |
} | |
addAll(upperEdgeVertices) | |
// Generate vertices for the centers of the caps of the cylinder | |
val lowerCenterIndex = size | |
add( | |
Vertex( | |
position = center + Size(y = -halfHeight), | |
normal = Direction(y = -1.0f), | |
uvCoordinate = UvCoordinate(x = 0.5f, y = 0.5f) | |
) | |
) | |
addAll(lowerCapVertices) | |
val upperCenterIndex = size | |
add( | |
Vertex( | |
position = center + Size(y = halfHeight), | |
normal = Direction(y = 1.0f), | |
uvCoordinate = UvCoordinate(x = 0.5f, y = 0.5f) | |
) | |
) | |
addAll(upperCapVertices) | |
}, | |
submeshes = mutableListOf<Submesh>().apply { | |
// Create triangles for each side | |
for (side in 0 until sideCount) { | |
val bottomRight = side + 1 | |
val topLeft = side + sideCount + 1 | |
val topRight = side + sideCount + 2 | |
val lowerCenterIndex = 2 * sideCount | |
val upperCenterIndex = lowerCenterIndex + 1 + sideCount | |
add( | |
Submesh( | |
// First triangle of side | |
side, topRight, bottomRight, | |
// Second triangle of side | |
side, topLeft, topRight, | |
// Add bottom cap triangle | |
lowerCenterIndex, lowerCenterIndex + side + 1, lowerCenterIndex + side + 2, | |
// Add top cap triangle | |
upperCenterIndex, upperCenterIndex + side + 2, lowerCenterIndex + side + 1 | |
) | |
) | |
} | |
}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment