-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathSpiralSphereGeometry.js
130 lines (85 loc) · 3.13 KB
/
SpiralSphereGeometry.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
/**
* @author munrocket / https://twitter.com/munrocket_twit
*/
import {
BufferGeometry,
Float32BufferAttribute
} from "./three.module.js";
var SpiralSphereGeometry = function ( radius, turns, gapX, gapY, tileX, tileY, tiles ) {
gapX = gapX / turns || 0;
gapY = gapY / turns || 0;
tileX = tileX || 8;
tileY = tileY || 8;
tiles = tiles || Math.floor( 4 * turns * turns / Math.PI );
var vertices = [];
var indices = [];
var ids = [];
var uvs = [];
function parameter( i ) {
return Math.acos( Math.cos( Math.PI / 2 / turns ) * ( 1 - 2 * i / ( ( tiles - 2 ) * tileX ) ) )
- ( turns + 1 ) * Math.PI / 2 / turns;
}
function pushVert( theta, phi ) {
var x = radius * Math.cos( theta ) * Math.cos( phi )
var y = - radius * Math.sin( theta );
var z = radius * Math.cos( theta ) * Math.sin( phi );
vertices.push( x, y, z );
}
for ( var id = 0; id < tiles - 2; id ++ ) {
for ( var i = 0; i <= tileX; i ++ ) {
var u = i / tileX;
var t = parameter( id * tileX + i + 2 * turns * ( gapY - 2 * gapY * u + ( gapY - 2 * gapY * id / ( tiles - 2 ) ) / 3 ) );
for ( var j = 0; j <= tileY; j ++ ) {
var v = j / tileY;
pushVert( t + gapX - ( 2 * gapX - Math.PI / turns ) * v, ( Math.PI + 2 * t ) * turns );
ids.push( id + 1 );
uvs.push( 1 - u, 1 - v );
}
}
for ( var i = 0; i < tileX; i ++ ) {
for ( var j = 0; j < tileY; j ++ ) {
var k = ( tileY + 1 ) * ( id * ( tileX + 1 ) + i ) + j;
indices.push( k + tileY + 1, k + 1, k );
indices.push( k + tileY + 2, k + 1, k + tileY + 1 );
}
}
}
/* Special case for the poles */
var iMax = 1 + Math.floor( ( tiles - 2 ) * tileX / 4 *
( 1 - Math.sin( ( turns + 3 ) * Math.PI / 2 / turns ) / Math.cos( Math.PI / 2 / turns ) ) );
var skip = ( tiles - 2 ) * ( tileX + 1 ) * ( tileY + 1 );
var t0 = - Math.PI / 2;
for ( var pol = 0; pol < 2; pol ++ ) {
var sign = 1 - 2 * pol;
for ( var i = 0; i <= iMax; i ++ ) {
var u = i / iMax;
var t = t0 + u * ( Math.PI / turns ) - gapY * u / turns;
var gapP = ( gapX > 0 ) ? gapX * Math.pow( u, Math.PI / gapX / turns ) : 0;
var t1 = t0 + gapP;
var t2 = Math.max( t0, t - gapX );
t2 = ( t1 < t2 ) ? t2 : t1;
for ( var j = 0; j <= tileY; j ++ ) {
var v = j / tileY;
pushVert( sign * ( t1 * ( 1 - v ) + t2 * v ), turns * ( Math.PI + sign * 2 * t ) );
ids.push( pol * ( tiles - 1 ) );
uvs.push( 1 - u, 1 - pol - sign * v );
}
}
for ( var i = 0; i < iMax; i ++ ) {
for ( var j = 0; j < tileY; j ++ ) {
var k = skip + ( tileY + 1 ) * ( pol * ( iMax + 1 ) + i ) + j;
indices.push( k + tileY + 1, k + 1, k );
indices.push( k + tileY + 2, k + 1, k + tileY + 1 );
}
}
}
var geometry = new BufferGeometry();
geometry.setIndex( indices );
geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) );
geometry.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) );
geometry.setAttribute( 'id', new Float32BufferAttribute( ids, 1 ) );
return geometry;
}
SpiralSphereGeometry.prototype = Object.create( BufferGeometry.prototype );
SpiralSphereGeometry.prototype.constructor = SpiralSphereGeometry;
export { SpiralSphereGeometry };