1 |
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 | import { Geometry } from '../core/Geometry.js';
|
9 | import { BufferGeometry } from '../core/BufferGeometry.js';
|
10 | import { Float32BufferAttribute } from '../core/BufferAttribute.js';
|
11 | import { Vector3 } from '../math/Vector3.js';
|
12 | import { Vector2 } from '../math/Vector2.js';
|
13 |
|
14 |
|
15 |
|
16 | function PolyhedronGeometry( vertices, indices, radius, detail ) {
|
17 |
|
18 | Geometry.call( this );
|
19 |
|
20 | this.type = 'PolyhedronGeometry';
|
21 |
|
22 | this.parameters = {
|
23 | vertices: vertices,
|
24 | indices: indices,
|
25 | radius: radius,
|
26 | detail: detail
|
27 | };
|
28 |
|
29 | this.fromBufferGeometry( new PolyhedronBufferGeometry( vertices, indices, radius, detail ) );
|
30 | this.mergeVertices();
|
31 |
|
32 | }
|
33 |
|
34 | PolyhedronGeometry.prototype = Object.create( Geometry.prototype );
|
35 | PolyhedronGeometry.prototype.constructor = PolyhedronGeometry;
|
36 |
|
37 |
|
38 |
|
39 | function PolyhedronBufferGeometry( vertices, indices, radius, detail ) {
|
40 |
|
41 | BufferGeometry.call( this );
|
42 |
|
43 | this.type = 'PolyhedronBufferGeometry';
|
44 |
|
45 | this.parameters = {
|
46 | vertices: vertices,
|
47 | indices: indices,
|
48 | radius: radius,
|
49 | detail: detail
|
50 | };
|
51 |
|
52 | radius = radius || 1;
|
53 | detail = detail || 0;
|
54 |
|
55 |
|
56 |
|
57 | var vertexBuffer = [];
|
58 | var uvBuffer = [];
|
59 |
|
60 |
|
61 |
|
62 | subdivide( detail );
|
63 |
|
64 |
|
65 |
|
66 | appplyRadius( radius );
|
67 |
|
68 |
|
69 |
|
70 | generateUVs();
|
71 |
|
72 |
|
73 |
|
74 | this.addAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) );
|
75 | this.addAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) );
|
76 | this.addAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) );
|
77 |
|
78 | if ( detail === 0 ) {
|
79 |
|
80 | this.computeVertexNormals();
|
81 |
|
82 | } else {
|
83 |
|
84 | this.normalizeNormals();
|
85 |
|
86 | }
|
87 |
|
88 |
|
89 |
|
90 | function subdivide( detail ) {
|
91 |
|
92 | var a = new Vector3();
|
93 | var b = new Vector3();
|
94 | var c = new Vector3();
|
95 |
|
96 |
|
97 |
|
98 | for ( var i = 0; i < indices.length; i += 3 ) {
|
99 |
|
100 |
|
101 |
|
102 | getVertexByIndex( indices[ i + 0 ], a );
|
103 | getVertexByIndex( indices[ i + 1 ], b );
|
104 | getVertexByIndex( indices[ i + 2 ], c );
|
105 |
|
106 |
|
107 |
|
108 | subdivideFace( a, b, c, detail );
|
109 |
|
110 | }
|
111 |
|
112 | }
|
113 |
|
114 | function subdivideFace( a, b, c, detail ) {
|
115 |
|
116 | var cols = Math.pow( 2, detail );
|
117 |
|
118 |
|
119 |
|
120 | var v = [];
|
121 |
|
122 | var i, j;
|
123 |
|
124 |
|
125 |
|
126 | for ( i = 0; i <= cols; i ++ ) {
|
127 |
|
128 | v[ i ] = [];
|
129 |
|
130 | var aj = a.clone().lerp( c, i / cols );
|
131 | var bj = b.clone().lerp( c, i / cols );
|
132 |
|
133 | var rows = cols - i;
|
134 |
|
135 | for ( j = 0; j <= rows; j ++ ) {
|
136 |
|
137 | if ( j === 0 && i === cols ) {
|
138 |
|
139 | v[ i ][ j ] = aj;
|
140 |
|
141 | } else {
|
142 |
|
143 | v[ i ][ j ] = aj.clone().lerp( bj, j / rows );
|
144 |
|
145 | }
|
146 |
|
147 | }
|
148 |
|
149 | }
|
150 |
|
151 |
|
152 |
|
153 | for ( i = 0; i < cols; i ++ ) {
|
154 |
|
155 | for ( j = 0; j < 2 * ( cols - i ) - 1; j ++ ) {
|
156 |
|
157 | var k = Math.floor( j / 2 );
|
158 |
|
159 | if ( j % 2 === 0 ) {
|
160 |
|
161 | pushVertex( v[ i ][ k + 1 ] );
|
162 | pushVertex( v[ i + 1 ][ k ] );
|
163 | pushVertex( v[ i ][ k ] );
|
164 |
|
165 | } else {
|
166 |
|
167 | pushVertex( v[ i ][ k + 1 ] );
|
168 | pushVertex( v[ i + 1 ][ k + 1 ] );
|
169 | pushVertex( v[ i + 1 ][ k ] );
|
170 |
|
171 | }
|
172 |
|
173 | }
|
174 |
|
175 | }
|
176 |
|
177 | }
|
178 |
|
179 | function appplyRadius( radius ) {
|
180 |
|
181 | var vertex = new Vector3();
|
182 |
|
183 |
|
184 |
|
185 | for ( var i = 0; i < vertexBuffer.length; i += 3 ) {
|
186 |
|
187 | vertex.x = vertexBuffer[ i + 0 ];
|
188 | vertex.y = vertexBuffer[ i + 1 ];
|
189 | vertex.z = vertexBuffer[ i + 2 ];
|
190 |
|
191 | vertex.normalize().multiplyScalar( radius );
|
192 |
|
193 | vertexBuffer[ i + 0 ] = vertex.x;
|
194 | vertexBuffer[ i + 1 ] = vertex.y;
|
195 | vertexBuffer[ i + 2 ] = vertex.z;
|
196 |
|
197 | }
|
198 |
|
199 | }
|
200 |
|
201 | function generateUVs() {
|
202 |
|
203 | var vertex = new Vector3();
|
204 |
|
205 | for ( var i = 0; i < vertexBuffer.length; i += 3 ) {
|
206 |
|
207 | vertex.x = vertexBuffer[ i + 0 ];
|
208 | vertex.y = vertexBuffer[ i + 1 ];
|
209 | vertex.z = vertexBuffer[ i + 2 ];
|
210 |
|
211 | var u = azimuth( vertex ) / 2 / Math.PI + 0.5;
|
212 | var v = inclination( vertex ) / Math.PI + 0.5;
|
213 | uvBuffer.push( u, 1 - v );
|
214 |
|
215 | }
|
216 |
|
217 | correctUVs();
|
218 |
|
219 | correctSeam();
|
220 |
|
221 | }
|
222 |
|
223 | function correctSeam() {
|
224 |
|
225 |
|
226 |
|
227 | for ( var i = 0; i < uvBuffer.length; i += 6 ) {
|
228 |
|
229 |
|
230 |
|
231 | var x0 = uvBuffer[ i + 0 ];
|
232 | var x1 = uvBuffer[ i + 2 ];
|
233 | var x2 = uvBuffer[ i + 4 ];
|
234 |
|
235 | var max = Math.max( x0, x1, x2 );
|
236 | var min = Math.min( x0, x1, x2 );
|
237 |
|
238 |
|
239 |
|
240 | if ( max > 0.9 && min < 0.1 ) {
|
241 |
|
242 | if ( x0 < 0.2 ) uvBuffer[ i + 0 ] += 1;
|
243 | if ( x1 < 0.2 ) uvBuffer[ i + 2 ] += 1;
|
244 | if ( x2 < 0.2 ) uvBuffer[ i + 4 ] += 1;
|
245 |
|
246 | }
|
247 |
|
248 | }
|
249 |
|
250 | }
|
251 |
|
252 | function pushVertex( vertex ) {
|
253 |
|
254 | vertexBuffer.push( vertex.x, vertex.y, vertex.z );
|
255 |
|
256 | }
|
257 |
|
258 | function getVertexByIndex( index, vertex ) {
|
259 |
|
260 | var stride = index * 3;
|
261 |
|
262 | vertex.x = vertices[ stride + 0 ];
|
263 | vertex.y = vertices[ stride + 1 ];
|
264 | vertex.z = vertices[ stride + 2 ];
|
265 |
|
266 | }
|
267 |
|
268 | function correctUVs() {
|
269 |
|
270 | var a = new Vector3();
|
271 | var b = new Vector3();
|
272 | var c = new Vector3();
|
273 |
|
274 | var centroid = new Vector3();
|
275 |
|
276 | var uvA = new Vector2();
|
277 | var uvB = new Vector2();
|
278 | var uvC = new Vector2();
|
279 |
|
280 | for ( var i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) {
|
281 |
|
282 | a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] );
|
283 | b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] );
|
284 | c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] );
|
285 |
|
286 | uvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] );
|
287 | uvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] );
|
288 | uvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] );
|
289 |
|
290 | centroid.copy( a ).add( b ).add( c ).divideScalar( 3 );
|
291 |
|
292 | var azi = azimuth( centroid );
|
293 |
|
294 | correctUV( uvA, j + 0, a, azi );
|
295 | correctUV( uvB, j + 2, b, azi );
|
296 | correctUV( uvC, j + 4, c, azi );
|
297 |
|
298 | }
|
299 |
|
300 | }
|
301 |
|
302 | function correctUV( uv, stride, vector, azimuth ) {
|
303 |
|
304 | if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) {
|
305 |
|
306 | uvBuffer[ stride ] = uv.x - 1;
|
307 |
|
308 | }
|
309 |
|
310 | if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) {
|
311 |
|
312 | uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5;
|
313 |
|
314 | }
|
315 |
|
316 | }
|
317 |
|
318 |
|
319 |
|
320 | function azimuth( vector ) {
|
321 |
|
322 | return Math.atan2( vector.z, - vector.x );
|
323 |
|
324 | }
|
325 |
|
326 |
|
327 |
|
328 |
|
329 | function inclination( vector ) {
|
330 |
|
331 | return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) );
|
332 |
|
333 | }
|
334 |
|
335 | }
|
336 |
|
337 | PolyhedronBufferGeometry.prototype = Object.create( BufferGeometry.prototype );
|
338 | PolyhedronBufferGeometry.prototype.constructor = PolyhedronBufferGeometry;
|
339 |
|
340 |
|
341 | export { PolyhedronGeometry, PolyhedronBufferGeometry };
|