mirror of
				https://github.com/jiawanlong/Cesium-Examples.git
				synced 2025-11-04 09:14:17 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			140 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			140 lines
		
	
	
		
			2.4 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
/**
 | 
						|
 * Parametric Surfaces Geometry
 | 
						|
 * based on the brilliant article by @prideout https://prideout.net/blog/old/blog/index.html@p=44.html
 | 
						|
 */
 | 
						|
 | 
						|
import {
 | 
						|
	BufferGeometry,
 | 
						|
	Float32BufferAttribute,
 | 
						|
	Vector3
 | 
						|
} from 'three';
 | 
						|
 | 
						|
class ParametricGeometry extends BufferGeometry {
 | 
						|
 | 
						|
	constructor( func = ( u, v, target ) => target.set( u, v, Math.cos( u ) * Math.sin( v ) ), slices = 8, stacks = 8 ) {
 | 
						|
 | 
						|
		super();
 | 
						|
 | 
						|
		this.type = 'ParametricGeometry';
 | 
						|
 | 
						|
		this.parameters = {
 | 
						|
			func: func,
 | 
						|
			slices: slices,
 | 
						|
			stacks: stacks
 | 
						|
		};
 | 
						|
 | 
						|
		// buffers
 | 
						|
 | 
						|
		const indices = [];
 | 
						|
		const vertices = [];
 | 
						|
		const normals = [];
 | 
						|
		const uvs = [];
 | 
						|
 | 
						|
		const EPS = 0.00001;
 | 
						|
 | 
						|
		const normal = new Vector3();
 | 
						|
 | 
						|
		const p0 = new Vector3(), p1 = new Vector3();
 | 
						|
		const pu = new Vector3(), pv = new Vector3();
 | 
						|
 | 
						|
		// generate vertices, normals and uvs
 | 
						|
 | 
						|
		const sliceCount = slices + 1;
 | 
						|
 | 
						|
		for ( let i = 0; i <= stacks; i ++ ) {
 | 
						|
 | 
						|
			const v = i / stacks;
 | 
						|
 | 
						|
			for ( let j = 0; j <= slices; j ++ ) {
 | 
						|
 | 
						|
				const 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 ( let i = 0; i < stacks; i ++ ) {
 | 
						|
 | 
						|
			for ( let j = 0; j < slices; j ++ ) {
 | 
						|
 | 
						|
				const a = i * sliceCount + j;
 | 
						|
				const b = i * sliceCount + j + 1;
 | 
						|
				const c = ( i + 1 ) * sliceCount + j + 1;
 | 
						|
				const 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.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
 | 
						|
		this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
 | 
						|
		this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
	copy( source ) {
 | 
						|
 | 
						|
		super.copy( source );
 | 
						|
 | 
						|
		this.parameters = Object.assign( {}, source.parameters );
 | 
						|
 | 
						|
		return this;
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
export { ParametricGeometry };
 |