fireball/lib/geometries/LatheGeometry.js
2018-12-25 17:29:22 +03:30

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 };