UNPKG

primitive-cylinder

Version:

A minimal 3D cylindrical geometry, including normals, UVs, and mesh.

137 lines (112 loc) 3.48 kB
function createCylinderMesh( radiusTop, radiusBottom, height, radialSegments, heightSegments ) { var index = 0 var indexOffset = 0 var indexArray = [] radiusTop = typeof radiusTop !== 'undefined' ? radiusTop : 1 radiusBottom = typeof radiusBottom !== 'undefined' ? radiusBottom : 1 height = typeof height !== 'undefined' ? height : 5 radialSegments = typeof radialSegments !== 'undefined' ? radialSegments : 64 heightSegments = typeof heightSegments !== 'undefined' ? heightSegments : 8 var capCount = 0 if (radiusTop > 0) { capCount++ } if (radiusBottom > 0) { capCount++ } var vertexCount = ((radialSegments + 1) * (heightSegments + 1)) + ((radialSegments + 2) * capCount) var cellCount = (radialSegments * heightSegments * 2) + (radialSegments * capCount) var normals = new Array(vertexCount) var vertices = new Array(vertexCount) var uvs = new Array(vertexCount) var cells = new Array(cellCount) var slope = (radiusBottom - radiusTop) / height var thetaLength = 2.0 * Math.PI for (var y = 0; y <= heightSegments; y++) { var indexRow = [] var v = y / heightSegments var radius = v * (radiusBottom - radiusTop) + radiusTop for (var x = 0; x <= radialSegments; x++) { var u = x / radialSegments var theta = u * thetaLength var sinTheta = Math.sin(theta) var cosTheta = Math.cos(theta) vertices[index] = [radius * sinTheta, -v * height + (height / 2), radius * cosTheta] normals[index] = [sinTheta, slope, cosTheta] uvs[index] = [u, 1 - v] indexRow.push(index) index++ } indexArray.push(indexRow) } for (var x = 0; x < radialSegments; x++) { for (var y = 0; y < heightSegments; y++) { var i1 = indexArray[y][x] var i2 = indexArray[y + 1][x] var i3 = indexArray[y + 1][x + 1] var i4 = indexArray[y][x + 1] // face one cells[indexOffset] = [i1, i2, i4] indexOffset++ // face two cells[indexOffset] = [i2, i3, i4] indexOffset++ } } var generateCap = function (top) { var vertex = new Array(3).fill(0) var radius = (top === true) ? radiusTop : radiusBottom var sign = (top === true) ? 1 : -1 var centerIndexStart = index for (var x = 1; x <= radialSegments; x++) { vertices[index] = [0, height * sign / 2, 0] normals[index] = [0, sign, 0] uvs[index] = [0.5, 0.5] index++ } var centerIndexEnd = index for (var x = 0; x <= radialSegments; x++) { var u = x / radialSegments var theta = u * thetaLength var cosTheta = Math.cos(theta) var sinTheta = Math.sin(theta) vertices[index] = [radius * sinTheta, height * sign / 2, radius * cosTheta] normals[index] = [0, sign, 0] uvs[index] = [(cosTheta * 0.5) + 0.5, (sinTheta * 0.5 * sign) + 0.5] index++ } for (var x = 0; x < radialSegments; x++) { var c = centerIndexStart + x var i = centerIndexEnd + x if ( top === true ) { // face top cells[indexOffset] = [i, i + 1, c] indexOffset++ } else { // face bottom cells[indexOffset] = [i + 1, i, c] indexOffset++ } } } if (radiusTop > 0) { generateCap(true) } if (radiusBottom > 0) { generateCap(false) } return { uvs: uvs, cells: cells, normals: normals, positions: vertices } } module.exports = createCylinderMesh