@@ -105,4 +105,158 @@ function createTorus(i, count) {
105
105
) ;
106
106
}
107
107
108
- const patterns = [ createGrid , createSphere , createSpiral , createHelix , createTorus ] ;
108
+ function createVortex ( i , count ) {
109
+ // Vortex parameters
110
+ const height = 60 ; // Total height of the vortex
111
+ const maxRadius = 35 ; // Maximum radius at the top
112
+ const minRadius = 5 ; // Minimum radius at the bottom
113
+ const numRotations = 3 ; // Number of full rotations from top to bottom
114
+
115
+ // Calculate normalized height position (0 = bottom, 1 = top)
116
+ const t = i / count ;
117
+
118
+ // Add some randomness to distribute particles more naturally
119
+ const randomOffset = 0.05 * Math . random ( ) ;
120
+ const heightPosition = t + randomOffset ;
121
+
122
+ // Calculate radius that decreases from top to bottom
123
+ const radius = minRadius + ( maxRadius - minRadius ) * heightPosition ;
124
+
125
+ // Calculate angle with more rotations at the bottom
126
+ const angle = numRotations * Math . PI * 2 * ( 1 - heightPosition ) + ( i * 0.1 ) ;
127
+
128
+ // Calculate the vertical position (from bottom to top)
129
+ const y = ( heightPosition - 0.5 ) * height ;
130
+
131
+ return new THREE . Vector3 (
132
+ Math . cos ( angle ) * radius ,
133
+ y ,
134
+ Math . sin ( angle ) * radius
135
+ ) ;
136
+ }
137
+
138
+ function createGalaxy ( i , count ) {
139
+ // Galaxy parameters
140
+ const numArms = 4 ; // Number of spiral arms
141
+ const armWidth = 0.15 ; // Width of each arm (0-1)
142
+ const maxRadius = 40 ; // Maximum radius of the galaxy
143
+ const thickness = 5 ; // Vertical thickness
144
+ const twistFactor = 2.5 ; // How much the arms twist
145
+
146
+ // Determine which arm this particle belongs to
147
+ const armIndex = i % numArms ;
148
+ const indexInArm = Math . floor ( i / numArms ) / Math . floor ( count / numArms ) ;
149
+
150
+ // Calculate radial distance from center
151
+ const radialDistance = indexInArm * maxRadius ;
152
+
153
+ // Add some randomness for arm width
154
+ const randomOffset = ( Math . random ( ) * 2 - 1 ) * armWidth ;
155
+
156
+ // Calculate angle with twist that increases with distance
157
+ const armOffset = ( 2 * Math . PI / numArms ) * armIndex ;
158
+ const twistAmount = twistFactor * indexInArm ;
159
+ const angle = armOffset + twistAmount + randomOffset ;
160
+
161
+ // Add height variation that decreases with distance from center
162
+ const verticalPosition = ( Math . random ( ) * 2 - 1 ) * thickness * ( 1 - indexInArm * 0.8 ) ;
163
+
164
+ return new THREE . Vector3 (
165
+ Math . cos ( angle ) * radialDistance ,
166
+ verticalPosition ,
167
+ Math . sin ( angle ) * radialDistance
168
+ ) ;
169
+ }
170
+
171
+ function createWave ( i , count ) {
172
+ // Wave/ocean parameters
173
+ const width = 60 ; // Total width of the wave field
174
+ const depth = 60 ; // Total depth of the wave field
175
+ const waveHeight = 10 ; // Maximum height of waves
176
+ const waveDensity = 0.1 ; // Controls wave frequency
177
+
178
+ // Create a grid of points (similar to your grid function but for a 2D plane)
179
+ const gridSize = Math . ceil ( Math . sqrt ( count ) ) ;
180
+ const spacingX = width / gridSize ;
181
+ const spacingZ = depth / gridSize ;
182
+
183
+ // Calculate 2D grid position
184
+ const ix = i % gridSize ;
185
+ const iz = Math . floor ( i / gridSize ) ;
186
+
187
+ // Convert to actual coordinates with proper spacing
188
+ const halfWidth = width / 2 ;
189
+ const halfDepth = depth / 2 ;
190
+ const x = ix * spacingX - halfWidth ;
191
+ const z = iz * spacingZ - halfDepth ;
192
+
193
+ // Create wave pattern using multiple sine waves for a more natural look
194
+ // We use the x and z coordinates to create a position-based wave pattern
195
+ const y = Math . sin ( x * waveDensity ) * Math . cos ( z * waveDensity ) * waveHeight +
196
+ Math . sin ( x * waveDensity * 2.5 ) * Math . cos ( z * waveDensity * 2.1 ) * ( waveHeight * 0.3 ) ;
197
+
198
+ return new THREE . Vector3 ( x , y , z ) ;
199
+ }
200
+
201
+ function createMobius ( i , count ) {
202
+ // Möbius strip parameters
203
+ const radius = 25 ; // Major radius of the strip
204
+ const width = 10 ; // Width of the strip
205
+
206
+ // Distribute points evenly along the length of the Möbius strip
207
+ // and across its width
208
+ const lengthSteps = Math . sqrt ( count ) ;
209
+ const widthSteps = count / lengthSteps ;
210
+
211
+ // Calculate position along length and width of strip
212
+ const lengthIndex = i % lengthSteps ;
213
+ const widthIndex = Math . floor ( i / lengthSteps ) % widthSteps ;
214
+
215
+ // Normalize to 0-1 range
216
+ const u = lengthIndex / lengthSteps ; // Position around the strip (0 to 1)
217
+ const v = ( widthIndex / widthSteps ) - 0.5 ; // Position across width (-0.5 to 0.5)
218
+
219
+ // Parametric equations for Möbius strip
220
+ const theta = u * Math . PI * 2 ; // Full loop around
221
+
222
+ // Calculate the Möbius strip coordinates
223
+ // This creates a half-twist in the strip
224
+ const x = ( radius + width * v * Math . cos ( theta / 2 ) ) * Math . cos ( theta ) ;
225
+ const y = ( radius + width * v * Math . cos ( theta / 2 ) ) * Math . sin ( theta ) ;
226
+ const z = width * v * Math . sin ( theta / 2 ) ;
227
+
228
+ return new THREE . Vector3 ( x , y , z ) ;
229
+ }
230
+
231
+ function createSupernova ( i , count ) {
232
+ // Supernova parameters
233
+ const maxRadius = 40 ; // Maximum explosion radius
234
+ const coreSize = 0.2 ; // Size of the dense core (0-1)
235
+ const outerDensity = 0.7 ; // Density of particles in outer shell
236
+
237
+ // Use golden ratio distribution for even spherical coverage
238
+ const phi = Math . acos ( 1 - 2 * ( i / count ) ) ;
239
+ const theta = Math . PI * 2 * i * ( 1 + Math . sqrt ( 5 ) ) ;
240
+
241
+ // Calculate radial distance with more particles near center and at outer shell
242
+ let normalizedRadius ;
243
+ const random = Math . random ( ) ;
244
+
245
+ if ( i < count * coreSize ) {
246
+ // Dense core - distribute within inner radius
247
+ normalizedRadius = Math . pow ( random , 0.5 ) * 0.3 ;
248
+ } else {
249
+ // Explosion wave - distribute with more particles at the outer shell
250
+ normalizedRadius = 0.3 + Math . pow ( random , outerDensity ) * 0.7 ;
251
+ }
252
+
253
+ // Scale to max radius
254
+ const radius = normalizedRadius * maxRadius ;
255
+
256
+ // Convert spherical to Cartesian coordinates
257
+ return new THREE . Vector3 (
258
+ Math . sin ( phi ) * Math . cos ( theta ) * radius ,
259
+ Math . sin ( phi ) * Math . sin ( theta ) * radius ,
260
+ Math . cos ( phi ) * radius
261
+ ) ;
262
+ }
0 commit comments