playcanvas
Version:
PlayCanvas WebGL game engine
84 lines (81 loc) • 3.98 kB
JavaScript
import { math } from '../../core/math/math.js';
import { calculateTangents } from './geometry-utils.js';
import { Geometry } from './geometry.js';
/**
* A procedural torus-shaped geometry.
*
* The size, shape and tesselation properties of the torus can be controlled via constructor
* parameters. By default, the function will create a torus in the XZ-plane with a tube radius of
* 0.2, a ring radius of 0.3, 30 segments and 20 sides.
*
* Note that the torus is created with UVs in the range of 0 to 1.
*
* @category Graphics
*/ class TorusGeometry extends Geometry {
/**
* Create a new TorusGeometry instance.
*
* @param {object} [opts] - An object that specifies optional inputs for the function as follows:
* @param {number} [opts.tubeRadius] - The radius of the tube forming the body of the torus
* (defaults to 0.2).
* @param {number} [opts.ringRadius] - The radius from the centre of the torus to the centre of the
* tube (defaults to 0.3).
* @param {number} [opts.sectorAngle] - The sector angle in degrees of the ring of the torus
* (defaults to 2 * Math.PI).
* @param {number} [opts.segments] - The number of radial divisions forming cross-sections of the
* torus ring (defaults to 20).
* @param {number} [opts.sides] - The number of divisions around the tubular body of the torus ring
* (defaults to 30).
* @param {boolean} [opts.calculateTangents] - Generate tangent information (defaults to false).
*/ constructor(opts = {}){
super();
var _opts_tubeRadius;
// Check the supplied options and provide defaults for unspecified ones
var rc = (_opts_tubeRadius = opts.tubeRadius) != null ? _opts_tubeRadius : 0.2;
var _opts_ringRadius;
var rt = (_opts_ringRadius = opts.ringRadius) != null ? _opts_ringRadius : 0.3;
var _opts_sectorAngle;
var sectorAngle = ((_opts_sectorAngle = opts.sectorAngle) != null ? _opts_sectorAngle : 360) * math.DEG_TO_RAD;
var _opts_segments;
var segments = (_opts_segments = opts.segments) != null ? _opts_segments : 30;
var _opts_sides;
var sides = (_opts_sides = opts.sides) != null ? _opts_sides : 20;
// Variable declarations
var positions = [];
var normals = [];
var uvs = [];
var indices = [];
for(var i = 0; i <= sides; i++){
for(var j = 0; j <= segments; j++){
var x = Math.cos(sectorAngle * j / segments) * (rt + rc * Math.cos(2 * Math.PI * i / sides));
var y = Math.sin(2 * Math.PI * i / sides) * rc;
var z = Math.sin(sectorAngle * j / segments) * (rt + rc * Math.cos(2 * Math.PI * i / sides));
var nx = Math.cos(sectorAngle * j / segments) * Math.cos(2 * Math.PI * i / sides);
var ny = Math.sin(2 * Math.PI * i / sides);
var nz = Math.sin(sectorAngle * j / segments) * Math.cos(2 * Math.PI * i / sides);
var u = i / sides;
var v = 1 - j / segments;
positions.push(x, y, z);
normals.push(nx, ny, nz);
uvs.push(u, 1.0 - v);
if (i < sides && j < segments) {
var first = i * (segments + 1) + j;
var second = (i + 1) * (segments + 1) + j;
var third = i * (segments + 1) + (j + 1);
var fourth = (i + 1) * (segments + 1) + (j + 1);
indices.push(first, second, third);
indices.push(second, fourth, third);
}
}
}
this.positions = positions;
this.normals = normals;
this.uvs = uvs;
this.uvs1 = uvs; // UV1 = UV0 for sphere
this.indices = indices;
if (opts.calculateTangents) {
this.tangents = calculateTangents(positions, normals, uvs, indices);
}
}
}
export { TorusGeometry };