File: /home/lindsay/xeolabs/xeogl-next/xeogl/src/geometry/torusGeometry.js
/**
A **TorusGeometry** is a parameterized {{#crossLink "Geometry"}}{{/crossLink}} that defines a torus-shaped mesh for attached {{#crossLink "Mesh"}}Meshes{{/crossLink}}.
<a href="../../examples/#geometry_primitives_torus"><img src="../../assets/images/screenshots/TorusGeometry.png"></img></a>
## Overview
* Dynamically modify a TorusGeometry's shape at any time by updating its {{#crossLink "TorusGeometry/center:property"}}{{/crossLink}}, {{#crossLink "TorusGeometry/radius:property"}}{{/crossLink}}, {{#crossLink "TorusGeometry/tube:property"}}{{/crossLink}},
{{#crossLink "TorusGeometry/radialSegments:property"}}{{/crossLink}}, {{#crossLink "TorusGeometry/tubeSegments:property"}}{{/crossLink}}, and
{{#crossLink "TorusGeometry/arc:property"}}{{/crossLink}} properties.
* Dynamically switch its primitive type between ````"points"````, ````"lines"```` and ````"triangles"```` at any time by
updating its {{#crossLink "Geometry/primitive:property"}}{{/crossLink}} property.
## Examples
* [Textured TorusGeometry](../../examples/#geometry_primitives_torus)
## Usage
An {{#crossLink "Mesh"}}{{/crossLink}} with a TorusGeometry and a {{#crossLink "PhongMaterial"}}{{/crossLink}} with
diffuse {{#crossLink "Texture"}}{{/crossLink}}:
````javascript
new xeogl.Mesh({
geometry: new xeogl.TorusGeometry({
center: [0,0,0],
radius: 1.0,
tube: 0.5,
radialSegments: 32,
tubeSegments: 24,
arc: Math.PI * 2.0
}),
material: new xeogl.PhongMaterial({
diffuseMap: new xeogl.Texture({
src: "textures/diffuse/uvGrid2.jpg"
})
})
});
````
@class TorusGeometry
@module xeogl
@submodule geometry
@constructor
@param [owner] {Component} Owner component. When destroyed, the owner will destroy this component as well. Creates this component within the default {{#crossLink "Scene"}}{{/crossLink}} when omitted.
@param [cfg] {*} Configs
@param [cfg.id] {String} Optional ID, unique among all components in the parent {{#crossLink "Scene"}}Scene{{/crossLink}},
generated automatically when omitted.
@param [cfg.meta] {String:Object} Optional map of user-defined metadata to attach to this TorusGeometry.
@param [cfg.primitive="triangles"] {String} The primitive type. Accepted values for a TorusGeometry are 'points', 'lines' and 'triangles'.
@param [cfg.center] {Float32Array} 3D point indicating the center position of the TorusGeometry.
@param [cfg.radius=1] {Number} The overall radius of the TorusGeometry.
@param [cfg.tube=0.3] {Number} The tube radius of the TorusGeometry.
@param [cfg.radialSegments=32] {Number} The number of radial segments that make up the TorusGeometry.
@param [cfg.tubeSegments=24] {Number} The number of tubular segments that make up the TorusGeometry.
@param [cfg.arc=Math.PI / 2.0] {Number} The length of the TorusGeometry's arc in radians, where Math.PI*2 is a closed torus.
@extends Geometry
*/
import {core} from "./../core.js";
import {utils} from "./../utils.js";
import {Geometry} from './geometry.js';
import {math} from '../math/math.js';
import {componentClasses} from "./../componentClasses.js";
const type = "xeogl.TorusGeometry";
class TorusGeometry extends Geometry {
/**
JavaScript class name for this Component.
For example: "xeogl.AmbientLight", "xeogl.MetallicMaterial" etc.
@property type
@type String
@final
*/
get type() {
return type;
}
init(cfg) {
let radius = cfg.radius || 1;
if (radius < 0) {
this.error("negative radius not allowed - will invert");
radius *= -1;
}
radius *= 0.5;
let tube = cfg.tube || 0.3;
if (tube < 0) {
this.error("negative tube not allowed - will invert");
tube *= -1;
}
let radialSegments = cfg.radialSegments || 32;
if (radialSegments < 0) {
this.error("negative radialSegments not allowed - will invert");
radialSegments *= -1;
}
if (radialSegments < 4) {
radialSegments = 4;
}
let tubeSegments = cfg.tubeSegments || 24;
if (tubeSegments < 0) {
this.error("negative tubeSegments not allowed - will invert");
tubeSegments *= -1;
}
if (tubeSegments < 4) {
tubeSegments = 4;
}
let arc = cfg.arc || Math.PI * 2;
if (arc < 0) {
this.warn("negative arc not allowed - will invert");
arc *= -1;
}
if (arc > 360) {
arc = 360;
}
const center = cfg.center;
let centerX = center ? center[0] : 0;
let centerY = center ? center[1] : 0;
const centerZ = center ? center[2] : 0;
const positions = [];
const normals = [];
const uvs = [];
const indices = [];
let u;
let v;
let x;
let y;
let z;
let vec;
let i;
let j;
for (j = 0; j <= tubeSegments; j++) {
for (i = 0; i <= radialSegments; i++) {
u = i / radialSegments * arc;
v = 0.785398 + (j / tubeSegments * Math.PI * 2);
centerX = radius * Math.cos(u);
centerY = radius * Math.sin(u);
x = (radius + tube * Math.cos(v) ) * Math.cos(u);
y = (radius + tube * Math.cos(v) ) * Math.sin(u);
z = tube * Math.sin(v);
positions.push(x + centerX);
positions.push(y + centerY);
positions.push(z + centerZ);
uvs.push(1 - (i / radialSegments));
uvs.push((j / tubeSegments));
vec = math.normalizeVec3(math.subVec3([x, y, z], [centerX, centerY, centerZ], []), []);
normals.push(vec[0]);
normals.push(vec[1]);
normals.push(vec[2]);
}
}
let a;
let b;
let c;
let d;
for (j = 1; j <= tubeSegments; j++) {
for (i = 1; i <= radialSegments; i++) {
a = ( radialSegments + 1 ) * j + i - 1;
b = ( radialSegments + 1 ) * ( j - 1 ) + i - 1;
c = ( radialSegments + 1 ) * ( j - 1 ) + i;
d = ( radialSegments + 1 ) * j + i;
indices.push(a);
indices.push(b);
indices.push(c);
indices.push(c);
indices.push(d);
indices.push(a);
}
}
super.init(utils.apply(cfg, {
positions: positions,
normals: normals,
uv: uvs,
indices: indices
}));
}
}
componentClasses[type] = TorusGeometry;
export {TorusGeometry};