molstar
Version:
A comprehensive macromolecular library.
129 lines • 5.24 kB
JavaScript
"use strict";
/**
* Copyright (c) 2018 mol* contributors, licensed under MIT, See LICENSE file for more info.
*
* @author Alexander Rose <alexander.rose@weirdbyte.de>
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.Cylinder = exports.DefaultCylinderProps = void 0;
var tslib_1 = require("tslib");
// adapted from three.js, MIT License Copyright 2010-2018 three.js authors
var linear_algebra_1 = require("../../mol-math/linear-algebra");
exports.DefaultCylinderProps = {
radiusTop: 1,
radiusBottom: 1,
height: 1,
radialSegments: 8,
heightSegments: 1,
topCap: false,
bottomCap: false,
thetaStart: 0.0,
thetaLength: Math.PI * 2
};
function Cylinder(props) {
var _a = (0, tslib_1.__assign)((0, tslib_1.__assign)({}, exports.DefaultCylinderProps), props), radiusTop = _a.radiusTop, radiusBottom = _a.radiusBottom, height = _a.height, radialSegments = _a.radialSegments, heightSegments = _a.heightSegments, topCap = _a.topCap, bottomCap = _a.bottomCap, thetaStart = _a.thetaStart, thetaLength = _a.thetaLength;
// buffers
var indices = [];
var vertices = [];
var normals = [];
// helper variables
var index = 0;
var indexArray = [];
var halfHeight = height / 2;
// generate geometry
generateTorso();
if (topCap && radiusTop > 0)
generateCap(true);
if (bottomCap && radiusBottom > 0)
generateCap(false);
return {
vertices: new Float32Array(vertices),
normals: new Float32Array(normals),
indices: new Uint32Array(indices)
};
function generateTorso() {
var normal = linear_algebra_1.Vec3.zero();
// this will be used to calculate the normal
var slope = (radiusBottom - radiusTop) / height;
// generate vertices, normals and uvs
for (var y = 0; y <= heightSegments; ++y) {
var indexRow = [];
var v = y / heightSegments;
// calculate the radius of the current row
var radius = v * (radiusBottom - radiusTop) + radiusTop;
for (var x = 0; x <= radialSegments; ++x) {
var u = x / radialSegments;
var theta = u * thetaLength + thetaStart;
var sinTheta = Math.sin(theta);
var cosTheta = Math.cos(theta);
// vertex
vertices.push(radius * sinTheta, -v * height + halfHeight, radius * cosTheta);
// normal
linear_algebra_1.Vec3.normalize(normal, linear_algebra_1.Vec3.set(normal, sinTheta, slope, cosTheta));
normals.push.apply(normals, normal);
// save index of vertex in respective row
indexRow.push(index++);
}
// now save vertices of the row in our index array
indexArray.push(indexRow);
}
// generate indices
for (var x = 0; x < radialSegments; ++x) {
for (var y = 0; y < heightSegments; ++y) {
// we use the index array to access the correct indices
var a = indexArray[y][x];
var b = indexArray[y + 1][x];
var c = indexArray[y + 1][x + 1];
var d = indexArray[y][x + 1];
// faces
indices.push(a, b, d);
indices.push(b, c, d);
}
}
}
function generateCap(top) {
var radius = (top === true) ? radiusTop : radiusBottom;
var sign = (top === true) ? 1 : -1;
// save the index of the first center vertex
var centerIndexStart = index;
// first we generate the center vertex data of the cap.
// because the geometry needs one set of uvs per face,
// we must generate a center vertex per face/segment
for (var x = 1; x <= radialSegments; ++x) {
// vertex
vertices.push(0, halfHeight * sign, 0);
// normal
normals.push(0, sign, 0);
// increase index
++index;
}
// save the index of the last center vertex
var centerIndexEnd = index;
// now we generate the surrounding vertices, normals and uvs
for (var x = 0; x <= radialSegments; ++x) {
var u = x / radialSegments;
var theta = u * thetaLength + thetaStart;
var cosTheta = Math.cos(theta);
var sinTheta = Math.sin(theta);
// vertex
vertices.push(radius * sinTheta, halfHeight * sign, radius * cosTheta);
// normal
normals.push(0, sign, 0);
// increase index
++index;
}
// generate indices
for (var x = 0; x < radialSegments; ++x) {
var c = centerIndexStart + x;
var i = centerIndexEnd + x;
if (top === true) {
indices.push(i, i + 1, c); // face top
}
else {
indices.push(i + 1, i, c); // face bottom
}
}
}
}
exports.Cylinder = Cylinder;
//# sourceMappingURL=cylinder.js.map