164 lines
3.1 KiB
JavaScript
164 lines
3.1 KiB
JavaScript
|
/**
|
||
|
* @author zz85 / https://github.com/zz85
|
||
|
* @author Mugen87 / https://github.com/Mugen87
|
||
|
*
|
||
|
* Parametric Surfaces Geometry
|
||
|
* based on the brilliant article by @prideout http://prideout.net/blog/?p=44
|
||
|
*/
|
||
|
|
||
|
import { Geometry } from '../core/Geometry.js';
|
||
|
import { BufferGeometry } from '../core/BufferGeometry.js';
|
||
|
import { Float32BufferAttribute } from '../core/BufferAttribute.js';
|
||
|
import { Vector3 } from '../math/Vector3.js';
|
||
|
|
||
|
// ParametricGeometry
|
||
|
|
||
|
function ParametricGeometry( func, slices, stacks ) {
|
||
|
|
||
|
Geometry.call( this );
|
||
|
|
||
|
this.type = 'ParametricGeometry';
|
||
|
|
||
|
this.parameters = {
|
||
|
func: func,
|
||
|
slices: slices,
|
||
|
stacks: stacks
|
||
|
};
|
||
|
|
||
|
this.fromBufferGeometry( new ParametricBufferGeometry( func, slices, stacks ) );
|
||
|
this.mergeVertices();
|
||
|
|
||
|
}
|
||
|
|
||
|
ParametricGeometry.prototype = Object.create( Geometry.prototype );
|
||
|
ParametricGeometry.prototype.constructor = ParametricGeometry;
|
||
|
|
||
|
// ParametricBufferGeometry
|
||
|
|
||
|
function ParametricBufferGeometry( func, slices, stacks ) {
|
||
|
|
||
|
BufferGeometry.call( this );
|
||
|
|
||
|
this.type = 'ParametricBufferGeometry';
|
||
|
|
||
|
this.parameters = {
|
||
|
func: func,
|
||
|
slices: slices,
|
||
|
stacks: stacks
|
||
|
};
|
||
|
|
||
|
// buffers
|
||
|
|
||
|
var indices = [];
|
||
|
var vertices = [];
|
||
|
var normals = [];
|
||
|
var uvs = [];
|
||
|
|
||
|
var EPS = 0.00001;
|
||
|
|
||
|
var normal = new Vector3();
|
||
|
|
||
|
var p0 = new Vector3(), p1 = new Vector3();
|
||
|
var pu = new Vector3(), pv = new Vector3();
|
||
|
|
||
|
var i, j;
|
||
|
|
||
|
if ( func.length < 3 ) {
|
||
|
|
||
|
console.error( 'THREE.ParametricGeometry: Function must now modify a Vector3 as third parameter.' );
|
||
|
|
||
|
}
|
||
|
|
||
|
// generate vertices, normals and uvs
|
||
|
|
||
|
var sliceCount = slices + 1;
|
||
|
|
||
|
for ( i = 0; i <= stacks; i ++ ) {
|
||
|
|
||
|
var v = i / stacks;
|
||
|
|
||
|
for ( j = 0; j <= slices; j ++ ) {
|
||
|
|
||
|
var u = j / slices;
|
||
|
|
||
|
// vertex
|
||
|
|
||
|
func( u, v, p0 );
|
||
|
vertices.push( p0.x, p0.y, p0.z );
|
||
|
|
||
|
// normal
|
||
|
|
||
|
// approximate tangent vectors via finite differences
|
||
|
|
||
|
if ( u - EPS >= 0 ) {
|
||
|
|
||
|
func( u - EPS, v, p1 );
|
||
|
pu.subVectors( p0, p1 );
|
||
|
|
||
|
} else {
|
||
|
|
||
|
func( u + EPS, v, p1 );
|
||
|
pu.subVectors( p1, p0 );
|
||
|
|
||
|
}
|
||
|
|
||
|
if ( v - EPS >= 0 ) {
|
||
|
|
||
|
func( u, v - EPS, p1 );
|
||
|
pv.subVectors( p0, p1 );
|
||
|
|
||
|
} else {
|
||
|
|
||
|
func( u, v + EPS, p1 );
|
||
|
pv.subVectors( p1, p0 );
|
||
|
|
||
|
}
|
||
|
|
||
|
// cross product of tangent vectors returns surface normal
|
||
|
|
||
|
normal.crossVectors( pu, pv ).normalize();
|
||
|
normals.push( normal.x, normal.y, normal.z );
|
||
|
|
||
|
// uv
|
||
|
|
||
|
uvs.push( u, v );
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// generate indices
|
||
|
|
||
|
for ( i = 0; i < stacks; i ++ ) {
|
||
|
|
||
|
for ( j = 0; j < slices; j ++ ) {
|
||
|
|
||
|
var a = i * sliceCount + j;
|
||
|
var b = i * sliceCount + j + 1;
|
||
|
var c = ( i + 1 ) * sliceCount + j + 1;
|
||
|
var d = ( i + 1 ) * sliceCount + j;
|
||
|
|
||
|
// faces one and two
|
||
|
|
||
|
indices.push( a, b, d );
|
||
|
indices.push( b, c, d );
|
||
|
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
// build geometry
|
||
|
|
||
|
this.setIndex( indices );
|
||
|
this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
|
||
|
this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
|
||
|
this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
|
||
|
|
||
|
}
|
||
|
|
||
|
ParametricBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
|
||
|
ParametricBufferGeometry.prototype.constructor = ParametricBufferGeometry;
|
||
|
|
||
|
|
||
|
export { ParametricGeometry, ParametricBufferGeometry };
|