three
Version:
JavaScript 3D library
127 lines (91 loc) • 3.53 kB
JavaScript
/**
* @author Mugen87 / https://github.com/Mugen87
*/
THREE.TorusBufferGeometry = function ( radius, tube, radialSegments, tubularSegments, arc ) {
THREE.BufferGeometry.call( this );
this.type = 'TorusBufferGeometry';
this.parameters = {
radius: radius,
tube: tube,
radialSegments: radialSegments,
tubularSegments: tubularSegments,
arc: arc
};
radius = radius || 100;
tube = tube || 40;
radialSegments = Math.floor( radialSegments ) || 8;
tubularSegments = Math.floor( tubularSegments ) || 6;
arc = arc || Math.PI * 2;
// used to calculate buffer length
var vertexCount = ( ( radialSegments + 1 ) * ( tubularSegments + 1 ) );
var indexCount = radialSegments * tubularSegments * 2 * 3;
// buffers
var indices = new ( indexCount > 65535 ? Uint32Array : Uint16Array )( indexCount );
var vertices = new Float32Array( vertexCount * 3 );
var normals = new Float32Array( vertexCount * 3 );
var uvs = new Float32Array( vertexCount * 2 );
// offset variables
var vertexBufferOffset = 0;
var uvBufferOffset = 0;
var indexBufferOffset = 0;
// helper variables
var center = new THREE.Vector3();
var vertex = new THREE.Vector3();
var normal = new THREE.Vector3();
var j, i;
// generate vertices, normals and uvs
for ( j = 0; j <= radialSegments; j ++ ) {
for ( i = 0; i <= tubularSegments; i ++ ) {
var u = i / tubularSegments * arc;
var v = j / radialSegments * Math.PI * 2;
// vertex
vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u );
vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u );
vertex.z = tube * Math.sin( v );
vertices[ vertexBufferOffset ] = vertex.x;
vertices[ vertexBufferOffset + 1 ] = vertex.y;
vertices[ vertexBufferOffset + 2 ] = vertex.z;
// this vector is used to calculate the normal
center.x = radius * Math.cos( u );
center.y = radius * Math.sin( u );
// normal
normal.subVectors( vertex, center ).normalize();
normals[ vertexBufferOffset ] = normal.x;
normals[ vertexBufferOffset + 1 ] = normal.y;
normals[ vertexBufferOffset + 2 ] = normal.z;
// uv
uvs[ uvBufferOffset ] = i / tubularSegments;
uvs[ uvBufferOffset + 1 ] = j / radialSegments;
// update offsets
vertexBufferOffset += 3;
uvBufferOffset += 2;
}
}
// generate indices
for ( j = 1; j <= radialSegments; j ++ ) {
for ( i = 1; i <= tubularSegments; i ++ ) {
// indices
var a = ( tubularSegments + 1 ) * j + i - 1;
var b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1;
var c = ( tubularSegments + 1 ) * ( j - 1 ) + i;
var d = ( tubularSegments + 1 ) * j + i;
// face one
indices[ indexBufferOffset ] = a;
indices[ indexBufferOffset + 1 ] = b;
indices[ indexBufferOffset + 2 ] = d;
// face two
indices[ indexBufferOffset + 3 ] = b;
indices[ indexBufferOffset + 4 ] = c;
indices[ indexBufferOffset + 5 ] = d;
// update offset
indexBufferOffset += 6;
}
}
// build geometry
this.setIndex( new THREE.BufferAttribute( indices, 1 ) );
this.addAttribute( 'position', new THREE.BufferAttribute( vertices, 3 ) );
this.addAttribute( 'normal', new THREE.BufferAttribute( normals, 3 ) );
this.addAttribute( 'uv', new THREE.BufferAttribute( uvs, 2 ) );
};
THREE.TorusBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
THREE.TorusBufferGeometry.prototype.constructor = THREE.TorusBufferGeometry;