UNPKG

3.05 kBJavaScriptView Raw
1/**
2 * @author zz85 / https://github.com/zz85
3 * @author Mugen87 / https://github.com/Mugen87
4 *
5 * Parametric Surfaces Geometry
6 * based on the brilliant article by @prideout http://prideout.net/blog/?p=44
7 */
8
9import { Geometry } from '../core/Geometry.js';
10import { BufferGeometry } from '../core/BufferGeometry.js';
11import { Float32BufferAttribute } from '../core/BufferAttribute.js';
12import { Vector3 } from '../math/Vector3.js';
13
14// ParametricGeometry
15
16function ParametricGeometry( func, slices, stacks ) {
17
18 Geometry.call( this );
19
20 this.type = 'ParametricGeometry';
21
22 this.parameters = {
23 func: func,
24 slices: slices,
25 stacks: stacks
26 };
27
28 this.fromBufferGeometry( new ParametricBufferGeometry( func, slices, stacks ) );
29 this.mergeVertices();
30
31}
32
33ParametricGeometry.prototype = Object.create( Geometry.prototype );
34ParametricGeometry.prototype.constructor = ParametricGeometry;
35
36// ParametricBufferGeometry
37
38function ParametricBufferGeometry( func, slices, stacks ) {
39
40 BufferGeometry.call( this );
41
42 this.type = 'ParametricBufferGeometry';
43
44 this.parameters = {
45 func: func,
46 slices: slices,
47 stacks: stacks
48 };
49
50 // buffers
51
52 var indices = [];
53 var vertices = [];
54 var normals = [];
55 var uvs = [];
56
57 var EPS = 0.00001;
58
59 var normal = new Vector3();
60
61 var p0 = new Vector3(), p1 = new Vector3();
62 var pu = new Vector3(), pv = new Vector3();
63
64 var i, j;
65
66 // generate vertices, normals and uvs
67
68 var sliceCount = slices + 1;
69
70 for ( i = 0; i <= stacks; i ++ ) {
71
72 var v = i / stacks;
73
74 for ( j = 0; j <= slices; j ++ ) {
75
76 var u = j / slices;
77
78 // vertex
79
80 func( u, v, p0 );
81 vertices.push( p0.x, p0.y, p0.z );
82
83 // normal
84
85 // approximate tangent vectors via finite differences
86
87 if ( u - EPS >= 0 ) {
88
89 func( u - EPS, v, p1 );
90 pu.subVectors( p0, p1 );
91
92 } else {
93
94 func( u + EPS, v, p1 );
95 pu.subVectors( p1, p0 );
96
97 }
98
99 if ( v - EPS >= 0 ) {
100
101 func( u, v - EPS, p1 );
102 pv.subVectors( p0, p1 );
103
104 } else {
105
106 func( u, v + EPS, p1 );
107 pv.subVectors( p1, p0 );
108
109 }
110
111 // cross product of tangent vectors returns surface normal
112
113 normal.crossVectors( pu, pv ).normalize();
114 normals.push( normal.x, normal.y, normal.z );
115
116 // uv
117
118 uvs.push( u, v );
119
120 }
121
122 }
123
124 // generate indices
125
126 for ( i = 0; i < stacks; i ++ ) {
127
128 for ( j = 0; j < slices; j ++ ) {
129
130 var a = i * sliceCount + j;
131 var b = i * sliceCount + j + 1;
132 var c = ( i + 1 ) * sliceCount + j + 1;
133 var d = ( i + 1 ) * sliceCount + j;
134
135 // faces one and two
136
137 indices.push( a, b, d );
138 indices.push( b, c, d );
139
140 }
141
142 }
143
144 // build geometry
145
146 this.setIndex( indices );
147 this.addAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
148 this.addAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) );
149 this.addAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
150
151}
152
153ParametricBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
154ParametricBufferGeometry.prototype.constructor = ParametricBufferGeometry;
155
156
157export { ParametricGeometry, ParametricBufferGeometry };