Spaces:
Running
Running
/** | |
* @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 }; | |