|
@@ -0,0 +1,156 @@
|
|
|
+/**
|
|
|
+ * @author Mugen87 / https://github.com/Mugen87
|
|
|
+ */
|
|
|
+
|
|
|
+ // points - to create a closed torus, one must use a set of points
|
|
|
+ // like so: [ a, b, c, d, a ], see first is the same as last.
|
|
|
+ // segments - the number of circumference segments to create
|
|
|
+ // phiStart - the starting radian
|
|
|
+ // phiLength - the radian (0 to 2PI) range of the lathed section
|
|
|
+ // 2PI is a closed lathe, less than 2PI is a portion.
|
|
|
+
|
|
|
+THREE.LatheBufferGeometry = function ( points, segments, phiStart, phiLength ) {
|
|
|
+
|
|
|
+ THREE.BufferGeometry.call( this );
|
|
|
+
|
|
|
+ this.type = 'LatheBufferGeometry';
|
|
|
+
|
|
|
+ this.parameters = {
|
|
|
+ points: points,
|
|
|
+ segments: segments,
|
|
|
+ phiStart: phiStart,
|
|
|
+ phiLength: phiLength
|
|
|
+ };
|
|
|
+
|
|
|
+ segments = Math.floor( segments ) || 12;
|
|
|
+ phiStart = phiStart || 0;
|
|
|
+ phiLength = phiLength || Math.PI * 2;
|
|
|
+
|
|
|
+ // clamp phiLength so it's in range of [ 0, 2PI ]
|
|
|
+ phiLength = THREE.Math.clamp( phiLength, 0, Math.PI * 2 );
|
|
|
+
|
|
|
+ // these are used to calculate buffer length
|
|
|
+ var vertexCount = ( segments + 1 ) * points.length;
|
|
|
+ var indexCount = segments * points.length * 2 * 3;
|
|
|
+
|
|
|
+ // buffers
|
|
|
+ var indices = new THREE.BufferAttribute( new ( indexCount > 65535 ? Uint32Array : Uint16Array )( indexCount ) , 1 );
|
|
|
+ var vertices = new THREE.BufferAttribute( new Float32Array( vertexCount * 3 ), 3 );
|
|
|
+ var uvs = new THREE.BufferAttribute( new Float32Array( vertexCount * 2 ), 2 );
|
|
|
+
|
|
|
+ // helper variables
|
|
|
+ var index = 0, indexOffset = 0, base;
|
|
|
+ var inversePointLength = 1.0 / ( points.length - 1 );
|
|
|
+ var inverseSegments = 1.0 / segments;
|
|
|
+ var vertex = new THREE.Vector3();
|
|
|
+ var uv = new THREE.Vector2();
|
|
|
+ var i, j;
|
|
|
+
|
|
|
+ // generate vertices and uvs
|
|
|
+
|
|
|
+ for ( i = 0; i <= segments; i ++ ) {
|
|
|
+
|
|
|
+ var phi = phiStart + i * inverseSegments * phiLength;
|
|
|
+
|
|
|
+ var sin = Math.sin( phi );
|
|
|
+ var cos = Math.cos( phi );
|
|
|
+
|
|
|
+ for ( j = 0; j <= ( points.length - 1 ); j ++ ) {
|
|
|
+
|
|
|
+ // vertex
|
|
|
+ vertex.x = points[ j ].x * sin;
|
|
|
+ vertex.y = points[ j ].y;
|
|
|
+ vertex.z = points[ j ].x * cos;
|
|
|
+ vertices.setXYZ( index, vertex.x, vertex.y, vertex.z );
|
|
|
+
|
|
|
+ // uv
|
|
|
+ uv.x = i / segments;
|
|
|
+ uv.y = j / ( points.length - 1 );
|
|
|
+ uvs.setXY( index, uv.x, uv.y );
|
|
|
+
|
|
|
+ // increase index
|
|
|
+ index ++;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // generate indices
|
|
|
+
|
|
|
+ for ( i = 0; i < segments; i ++ ) {
|
|
|
+
|
|
|
+ for ( j = 0; j < ( points.length - 1 ); j ++ ) {
|
|
|
+
|
|
|
+ base = j + i * points.length;
|
|
|
+
|
|
|
+ // indices
|
|
|
+ var a = base;
|
|
|
+ var b = base + points.length;
|
|
|
+ var c = base + points.length + 1;
|
|
|
+ var d = base + 1;
|
|
|
+
|
|
|
+ // face one
|
|
|
+ indices.setX( indexOffset, a ); indexOffset++;
|
|
|
+ indices.setX( indexOffset, b ); indexOffset++;
|
|
|
+ indices.setX( indexOffset, d ); indexOffset++;
|
|
|
+
|
|
|
+ // face two
|
|
|
+ indices.setX( indexOffset, b ); indexOffset++;
|
|
|
+ indices.setX( indexOffset, c ); indexOffset++;
|
|
|
+ indices.setX( indexOffset, d ); indexOffset++;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // build geometry
|
|
|
+
|
|
|
+ this.setIndex( indices );
|
|
|
+ this.addAttribute( 'position', vertices );
|
|
|
+ this.addAttribute( 'uv', uvs );
|
|
|
+
|
|
|
+ // generate normals
|
|
|
+
|
|
|
+ this.computeVertexNormals();
|
|
|
+
|
|
|
+ // if the geometry is closed, we need to merge the first and last normal of a vertex row
|
|
|
+ // because the corresponding vertices are identical (but still have different UVs).
|
|
|
+
|
|
|
+ if( phiLength === Math.PI * 2 ) {
|
|
|
+
|
|
|
+ var normals = this.attributes.normal.array;
|
|
|
+ var n1 = new THREE.Vector3();
|
|
|
+ var n2 = new THREE.Vector3();
|
|
|
+ var n = new THREE.Vector3();
|
|
|
+
|
|
|
+ // this is the buffer offset for the last line of vertices
|
|
|
+ base = segments * points.length * 3;
|
|
|
+
|
|
|
+ for( i = 0, j = 0; i < points.length; i ++, j += 3 ) {
|
|
|
+
|
|
|
+ // select the normal of the vertex in the first line
|
|
|
+ n1.x = normals[ j + 0 ];
|
|
|
+ n1.y = normals[ j + 1 ];
|
|
|
+ n1.z = normals[ j + 2 ];
|
|
|
+
|
|
|
+ // select the normal of the vertex in the last line
|
|
|
+ n2.x = normals[ base + j + 0 ];
|
|
|
+ n2.y = normals[ base + j + 1 ];
|
|
|
+ n2.z = normals[ base + j + 2 ];
|
|
|
+
|
|
|
+ // merge normals
|
|
|
+ n.addVectors( n1, n2 ).normalize();
|
|
|
+
|
|
|
+ // assign the new values to both normals
|
|
|
+ normals[ j + 0 ] = normals[ base + j + 0 ] = n.x;
|
|
|
+ normals[ j + 1 ] = normals[ base + j + 1 ] = n.y;
|
|
|
+ normals[ j + 2 ] = normals[ base + j + 2 ] = n.z;
|
|
|
+
|
|
|
+ } // next row
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+};
|
|
|
+
|
|
|
+THREE.LatheBufferGeometry.prototype = Object.create( THREE.BufferGeometry.prototype );
|
|
|
+THREE.LatheBufferGeometry.prototype.constructor = THREE.LatheBufferGeometry;
|