187 lines
3.9 KiB
JavaScript
187 lines
3.9 KiB
JavaScript
|
/**
|
||
|
* @author zz85 / https://github.com/zz85
|
||
|
* @author bhouston / http://clara.io
|
||
|
* @author Mugen87 / https://github.com/Mugen87
|
||
|
*/
|
||
|
|
||
|
import { Geometry } from '../core/Geometry.js';
|
||
|
import { Float32BufferAttribute } from '../core/BufferAttribute.js';
|
||
|
import { BufferGeometry } from '../core/BufferGeometry.js';
|
||
|
import { Vector3 } from '../math/Vector3.js';
|
||
|
import { Vector2 } from '../math/Vector2.js';
|
||
|
import { _Math } from '../math/Math.js';
|
||
|
|
||
|
// LatheGeometry
|
||
|
|
||
|
function LatheGeometry( points, segments, phiStart, phiLength ) {
|
||
|
|
||
|
Geometry.call( this );
|
||
|
|
||
|
this.type = 'LatheGeometry';
|
||
|
|
||
|
this.parameters = {
|
||
|
points: points,
|
||
|
segments: segments,
|
||
|
phiStart: phiStart,
|
||
|
phiLength: phiLength
|
||
|
};
|
||
|
|
||
|
this.fromBufferGeometry( new LatheBufferGeometry( points, segments, phiStart, phiLength ) );
|
||
|
this.mergeVertices();
|
||
|
|
||
|
}
|
||
|
|
||
|
LatheGeometry.prototype = Object.create( Geometry.prototype );
|
||
|
LatheGeometry.prototype.constructor = LatheGeometry;
|
||
|
|
||
|
// LatheBufferGeometry
|
||
|
|
||
|
function LatheBufferGeometry( points, segments, phiStart, phiLength ) {
|
||
|
|
||
|
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 = _Math.clamp( phiLength, 0, Math.PI * 2 );
|
||
|
|
||
|
|
||
|
// buffers
|
||
|
|
||
|
var indices = [];
|
||
|
var vertices = [];
|
||
|
var uvs = [];
|
||
|
|
||
|
// helper variables
|
||
|
|
||
|
var base;
|
||
|
var inverseSegments = 1.0 / segments;
|
||
|
var vertex = new Vector3();
|
||
|
var uv = new 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.push( vertex.x, vertex.y, vertex.z );
|
||
|
|
||
|
// uv
|
||
|
|
||
|
uv.x = i / segments;
|
||
|
uv.y = j / ( points.length - 1 );
|
||
|
|
||
|
uvs.push( uv.x, uv.y );
|
||
|
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// indices
|
||
|
|
||
|
for ( i = 0; i < segments; i ++ ) {
|
||
|
|
||
|
for ( j = 0; j < ( points.length - 1 ); j ++ ) {
|
||
|
|
||
|
base = j + i * points.length;
|
||
|
|
||
|
var a = base;
|
||
|
var b = base + points.length;
|
||
|
var c = base + points.length + 1;
|
||
|
var d = base + 1;
|
||
|
|
||
|
// faces
|
||
|
|
||
|
indices.push( a, b, d );
|
||
|
indices.push( b, c, d );
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// build geometry
|
||
|
|
||
|
this.setIndex( indices );
|
||
|
this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
|
||
|
this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
|
||
|
|
||
|
// generate normals
|
||
|
|
||
|
this.computeVertexNormals();
|
||
|
|
||
|
// if the geometry is closed, we need to average the normals along the seam.
|
||
|
// 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 Vector3();
|
||
|
var n2 = new Vector3();
|
||
|
var n = new 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 ];
|
||
|
|
||
|
// average 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;
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
LatheBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
|
||
|
LatheBufferGeometry.prototype.constructor = LatheBufferGeometry;
|
||
|
|
||
|
|
||
|
export { LatheGeometry, LatheBufferGeometry };
|