@guinetik/gcanvas 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/release.yaml +70 -0
- package/.jshintrc +4 -0
- package/.vscode/settings.json +22 -0
- package/CLAUDE.md +310 -0
- package/blackhole.jpg +0 -0
- package/demo.png +0 -0
- package/demos/CNAME +1 -0
- package/demos/animations.html +31 -0
- package/demos/basic.html +38 -0
- package/demos/baskara.html +31 -0
- package/demos/bezier.html +35 -0
- package/demos/beziersignature.html +29 -0
- package/demos/blackhole.html +28 -0
- package/demos/blob.html +35 -0
- package/demos/demos.css +289 -0
- package/demos/easing.html +28 -0
- package/demos/events.html +195 -0
- package/demos/fluent.html +647 -0
- package/demos/fractals.html +36 -0
- package/demos/genart.html +26 -0
- package/demos/gendream.html +26 -0
- package/demos/group.html +36 -0
- package/demos/home.html +587 -0
- package/demos/index.html +364 -0
- package/demos/isometric.html +34 -0
- package/demos/js/animations.js +452 -0
- package/demos/js/basic.js +204 -0
- package/demos/js/baskara.js +751 -0
- package/demos/js/bezier.js +692 -0
- package/demos/js/beziersignature.js +241 -0
- package/demos/js/blackhole/accretiondisk.obj.js +379 -0
- package/demos/js/blackhole/blackhole.obj.js +318 -0
- package/demos/js/blackhole/index.js +409 -0
- package/demos/js/blackhole/particle.js +56 -0
- package/demos/js/blackhole/starfield.obj.js +218 -0
- package/demos/js/blob.js +2263 -0
- package/demos/js/easing.js +477 -0
- package/demos/js/fluent.js +183 -0
- package/demos/js/fractals.js +931 -0
- package/demos/js/fractalworker.js +93 -0
- package/demos/js/genart.js +268 -0
- package/demos/js/gendream.js +209 -0
- package/demos/js/group.js +140 -0
- package/demos/js/info-toggle.js +25 -0
- package/demos/js/isometric.js +863 -0
- package/demos/js/kerr.js +1556 -0
- package/demos/js/lavalamp.js +590 -0
- package/demos/js/layout.js +354 -0
- package/demos/js/mondrian.js +285 -0
- package/demos/js/opacity.js +275 -0
- package/demos/js/painter.js +484 -0
- package/demos/js/particles-showcase.js +514 -0
- package/demos/js/particles.js +299 -0
- package/demos/js/patterns.js +397 -0
- package/demos/js/penrose/artifact.js +69 -0
- package/demos/js/penrose/blackhole.js +121 -0
- package/demos/js/penrose/constants.js +73 -0
- package/demos/js/penrose/game.js +943 -0
- package/demos/js/penrose/lore.js +278 -0
- package/demos/js/penrose/penrosescene.js +892 -0
- package/demos/js/penrose/ship.js +216 -0
- package/demos/js/penrose/sounds.js +211 -0
- package/demos/js/penrose/voidparticle.js +55 -0
- package/demos/js/penrose/voidscene.js +258 -0
- package/demos/js/penrose/voidship.js +144 -0
- package/demos/js/penrose/wormhole.js +46 -0
- package/demos/js/pipeline.js +555 -0
- package/demos/js/scene.js +304 -0
- package/demos/js/scenes.js +320 -0
- package/demos/js/schrodinger.js +410 -0
- package/demos/js/schwarzschild.js +1023 -0
- package/demos/js/shapes.js +628 -0
- package/demos/js/space/alien.js +171 -0
- package/demos/js/space/boom.js +98 -0
- package/demos/js/space/boss.js +353 -0
- package/demos/js/space/buff.js +73 -0
- package/demos/js/space/bullet.js +102 -0
- package/demos/js/space/constants.js +85 -0
- package/demos/js/space/game.js +1884 -0
- package/demos/js/space/hud.js +112 -0
- package/demos/js/space/laserbeam.js +179 -0
- package/demos/js/space/lightning.js +277 -0
- package/demos/js/space/minion.js +192 -0
- package/demos/js/space/missile.js +212 -0
- package/demos/js/space/player.js +430 -0
- package/demos/js/space/powerup.js +90 -0
- package/demos/js/space/starfield.js +58 -0
- package/demos/js/space/starpower.js +90 -0
- package/demos/js/spacetime.js +559 -0
- package/demos/js/svgtween.js +204 -0
- package/demos/js/tde/accretiondisk.js +418 -0
- package/demos/js/tde/blackhole.js +219 -0
- package/demos/js/tde/blackholescene.js +209 -0
- package/demos/js/tde/config.js +59 -0
- package/demos/js/tde/index.js +695 -0
- package/demos/js/tde/jets.js +290 -0
- package/demos/js/tde/lensedstarfield.js +147 -0
- package/demos/js/tde/tdestar.js +317 -0
- package/demos/js/tde/tidalstream.js +356 -0
- package/demos/js/tde_old/blackhole.obj.js +354 -0
- package/demos/js/tde_old/debris.obj.js +791 -0
- package/demos/js/tde_old/flare.obj.js +239 -0
- package/demos/js/tde_old/index.js +448 -0
- package/demos/js/tde_old/star.obj.js +812 -0
- package/demos/js/tiles.js +312 -0
- package/demos/js/tweendemo.js +79 -0
- package/demos/js/visibility.js +102 -0
- package/demos/kerr.html +28 -0
- package/demos/lavalamp.html +27 -0
- package/demos/layouts.html +37 -0
- package/demos/logo.svg +4 -0
- package/demos/loop.html +84 -0
- package/demos/mondrian.html +32 -0
- package/demos/og_image.png +0 -0
- package/demos/opacity.html +36 -0
- package/demos/painter.html +39 -0
- package/demos/particles-showcase.html +28 -0
- package/demos/particles.html +24 -0
- package/demos/patterns.html +33 -0
- package/demos/penrose-game.html +31 -0
- package/demos/pipeline.html +737 -0
- package/demos/scene.html +33 -0
- package/demos/scenes.html +96 -0
- package/demos/schrodinger.html +27 -0
- package/demos/schwarzschild.html +27 -0
- package/demos/shapes.html +16 -0
- package/demos/space.html +85 -0
- package/demos/spacetime.html +27 -0
- package/demos/svgtween.html +29 -0
- package/demos/tde.html +28 -0
- package/demos/tiles.html +28 -0
- package/demos/transforms.html +400 -0
- package/demos/tween.html +45 -0
- package/demos/visibility.html +33 -0
- package/disk_example.png +0 -0
- package/docs/README.md +222 -0
- package/docs/concepts/architecture-overview.md +204 -0
- package/docs/concepts/lifecycle.md +255 -0
- package/docs/concepts/rendering-pipeline.md +279 -0
- package/docs/concepts/tde-zorder.md +106 -0
- package/docs/concepts/two-layer-architecture.md +229 -0
- package/docs/getting-started/first-game.md +354 -0
- package/docs/getting-started/hello-world.md +269 -0
- package/docs/getting-started/installation.md +157 -0
- package/docs/modules/collision/README.md +453 -0
- package/docs/modules/fluent/README.md +1075 -0
- package/docs/modules/game/README.md +303 -0
- package/docs/modules/isometric-camera.md +210 -0
- package/docs/modules/isometric.md +275 -0
- package/docs/modules/painter/README.md +328 -0
- package/docs/modules/particle/README.md +559 -0
- package/docs/modules/shapes/README.md +221 -0
- package/docs/modules/shapes/base/euclidian.md +123 -0
- package/docs/modules/shapes/base/geometry2d.md +204 -0
- package/docs/modules/shapes/base/renderable.md +215 -0
- package/docs/modules/shapes/base/shape.md +262 -0
- package/docs/modules/shapes/base/transformable.md +243 -0
- package/docs/modules/shapes/hierarchy.md +218 -0
- package/docs/modules/state/README.md +577 -0
- package/docs/modules/util/README.md +99 -0
- package/docs/modules/util/camera3d.md +412 -0
- package/docs/modules/util/scene3d.md +395 -0
- package/index.html +17 -0
- package/jsdoc.json +50 -0
- package/package.json +55 -0
- package/readme.md +599 -0
- package/scripts/build-demo.js +69 -0
- package/scripts/bundle4llm.js +276 -0
- package/scripts/clearconsole.js +48 -0
- package/src/collision/collision-system.js +332 -0
- package/src/collision/collision.js +303 -0
- package/src/collision/index.js +10 -0
- package/src/fluent/fluent-game.js +430 -0
- package/src/fluent/fluent-go.js +1060 -0
- package/src/fluent/fluent-layer.js +152 -0
- package/src/fluent/fluent-scene.js +291 -0
- package/src/fluent/index.js +98 -0
- package/src/fluent/sketch.js +380 -0
- package/src/game/game.js +467 -0
- package/src/game/index.js +49 -0
- package/src/game/objects/go.js +220 -0
- package/src/game/objects/imagego.js +30 -0
- package/src/game/objects/index.js +54 -0
- package/src/game/objects/isometric-scene.js +260 -0
- package/src/game/objects/layoutscene.js +549 -0
- package/src/game/objects/scene.js +175 -0
- package/src/game/objects/scene3d.js +118 -0
- package/src/game/objects/text.js +221 -0
- package/src/game/objects/wrapper.js +232 -0
- package/src/game/pipeline.js +243 -0
- package/src/game/ui/button.js +396 -0
- package/src/game/ui/cursor.js +93 -0
- package/src/game/ui/fps.js +91 -0
- package/src/game/ui/index.js +5 -0
- package/src/game/ui/togglebutton.js +93 -0
- package/src/game/ui/tooltip.js +249 -0
- package/src/index.js +25 -0
- package/src/io/events.js +20 -0
- package/src/io/index.js +86 -0
- package/src/io/input.js +70 -0
- package/src/io/keys.js +152 -0
- package/src/io/mouse.js +61 -0
- package/src/io/touch.js +39 -0
- package/src/logger/debugtab.js +138 -0
- package/src/logger/index.js +3 -0
- package/src/logger/loggable.js +47 -0
- package/src/logger/logger.js +113 -0
- package/src/math/complex.js +37 -0
- package/src/math/constants.js +1 -0
- package/src/math/fractal.js +1271 -0
- package/src/math/gr.js +201 -0
- package/src/math/heat.js +202 -0
- package/src/math/index.js +12 -0
- package/src/math/noise.js +433 -0
- package/src/math/orbital.js +191 -0
- package/src/math/patterns.js +1339 -0
- package/src/math/penrose.js +259 -0
- package/src/math/quantum.js +115 -0
- package/src/math/random.js +195 -0
- package/src/math/tensor.js +1009 -0
- package/src/mixins/anchor.js +131 -0
- package/src/mixins/draggable.js +72 -0
- package/src/mixins/index.js +2 -0
- package/src/motion/bezier.js +132 -0
- package/src/motion/bounce.js +58 -0
- package/src/motion/easing.js +349 -0
- package/src/motion/float.js +130 -0
- package/src/motion/follow.js +125 -0
- package/src/motion/hop.js +52 -0
- package/src/motion/index.js +82 -0
- package/src/motion/motion.js +1124 -0
- package/src/motion/orbit.js +49 -0
- package/src/motion/oscillate.js +39 -0
- package/src/motion/parabolic.js +141 -0
- package/src/motion/patrol.js +147 -0
- package/src/motion/pendulum.js +48 -0
- package/src/motion/pulse.js +88 -0
- package/src/motion/shake.js +83 -0
- package/src/motion/spiral.js +144 -0
- package/src/motion/spring.js +150 -0
- package/src/motion/swing.js +47 -0
- package/src/motion/tween.js +92 -0
- package/src/motion/tweenetik.js +139 -0
- package/src/motion/waypoint.js +210 -0
- package/src/painter/index.js +8 -0
- package/src/painter/painter.colors.js +331 -0
- package/src/painter/painter.effects.js +230 -0
- package/src/painter/painter.img.js +229 -0
- package/src/painter/painter.js +295 -0
- package/src/painter/painter.lines.js +189 -0
- package/src/painter/painter.opacity.js +41 -0
- package/src/painter/painter.shapes.js +277 -0
- package/src/painter/painter.text.js +273 -0
- package/src/particle/emitter.js +124 -0
- package/src/particle/index.js +11 -0
- package/src/particle/particle-system.js +322 -0
- package/src/particle/particle.js +71 -0
- package/src/particle/updaters.js +170 -0
- package/src/shapes/arc.js +43 -0
- package/src/shapes/arrow.js +33 -0
- package/src/shapes/bezier.js +42 -0
- package/src/shapes/circle.js +62 -0
- package/src/shapes/clouds.js +56 -0
- package/src/shapes/cone.js +219 -0
- package/src/shapes/cross.js +70 -0
- package/src/shapes/cube.js +244 -0
- package/src/shapes/cylinder.js +254 -0
- package/src/shapes/diamond.js +48 -0
- package/src/shapes/euclidian.js +111 -0
- package/src/shapes/figure.js +115 -0
- package/src/shapes/geometry.js +220 -0
- package/src/shapes/group.js +375 -0
- package/src/shapes/heart.js +42 -0
- package/src/shapes/hexagon.js +26 -0
- package/src/shapes/image.js +192 -0
- package/src/shapes/index.js +111 -0
- package/src/shapes/line.js +29 -0
- package/src/shapes/pattern.js +90 -0
- package/src/shapes/pin.js +44 -0
- package/src/shapes/poly.js +31 -0
- package/src/shapes/prism.js +226 -0
- package/src/shapes/rect.js +35 -0
- package/src/shapes/renderable.js +333 -0
- package/src/shapes/ring.js +26 -0
- package/src/shapes/roundrect.js +95 -0
- package/src/shapes/shape.js +117 -0
- package/src/shapes/slice.js +26 -0
- package/src/shapes/sphere.js +314 -0
- package/src/shapes/sphere3d.js +537 -0
- package/src/shapes/square.js +15 -0
- package/src/shapes/star.js +99 -0
- package/src/shapes/svg.js +408 -0
- package/src/shapes/text.js +553 -0
- package/src/shapes/traceable.js +83 -0
- package/src/shapes/transform.js +357 -0
- package/src/shapes/transformable.js +172 -0
- package/src/shapes/triangle.js +26 -0
- package/src/sound/index.js +17 -0
- package/src/sound/sound.js +473 -0
- package/src/sound/synth.analyzer.js +149 -0
- package/src/sound/synth.effects.js +207 -0
- package/src/sound/synth.envelope.js +59 -0
- package/src/sound/synth.js +229 -0
- package/src/sound/synth.musical.js +160 -0
- package/src/sound/synth.noise.js +85 -0
- package/src/sound/synth.oscillators.js +293 -0
- package/src/state/index.js +10 -0
- package/src/state/state-machine.js +371 -0
- package/src/util/camera3d.js +438 -0
- package/src/util/index.js +6 -0
- package/src/util/isometric-camera.js +235 -0
- package/src/util/layout.js +317 -0
- package/src/util/position.js +147 -0
- package/src/util/tasks.js +47 -0
- package/src/util/zindex.js +287 -0
- package/src/webgl/index.js +9 -0
- package/src/webgl/shaders/sphere-shaders.js +994 -0
- package/src/webgl/webgl-renderer.js +388 -0
- package/tde.png +0 -0
- package/test/math/orbital.test.js +61 -0
- package/test/math/tensor.test.js +114 -0
- package/test/particle/emitter.test.js +204 -0
- package/test/particle/particle-system.test.js +310 -0
- package/test/particle/particle.test.js +116 -0
- package/test/particle/updaters.test.js +386 -0
- package/test/setup.js +120 -0
- package/test/shapes/euclidian.test.js +44 -0
- package/test/shapes/geometry.test.js +86 -0
- package/test/shapes/group.test.js +86 -0
- package/test/shapes/rectangle.test.js +64 -0
- package/test/shapes/transform.test.js +379 -0
- package/test/util/camera3d.test.js +428 -0
- package/test/util/scene3d.test.js +352 -0
- package/types/collision.d.ts +249 -0
- package/types/common.d.ts +155 -0
- package/types/game.d.ts +497 -0
- package/types/index.d.ts +309 -0
- package/types/io.d.ts +188 -0
- package/types/logger.d.ts +127 -0
- package/types/math.d.ts +268 -0
- package/types/mixins.d.ts +92 -0
- package/types/motion.d.ts +678 -0
- package/types/painter.d.ts +378 -0
- package/types/shapes.d.ts +864 -0
- package/types/sound.d.ts +672 -0
- package/types/state.d.ts +251 -0
- package/types/util.d.ts +253 -0
- package/vite.config.js +50 -0
- package/vitest.config.js +13 -0
|
@@ -0,0 +1,433 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* A speed-improved perlin and simplex noise algorithms for 2D.
|
|
3
|
+
*
|
|
4
|
+
* Based on example code by Stefan Gustavson (stegu@itn.liu.se).
|
|
5
|
+
* Optimisations by Peter Eastman (peastman@drizzle.stanford.edu).
|
|
6
|
+
* Better rank ordering method by Stefan Gustavson in 2012.
|
|
7
|
+
* Converted to Javascript by Joseph Gentle.
|
|
8
|
+
*
|
|
9
|
+
* Version 2012-03-09
|
|
10
|
+
*
|
|
11
|
+
* This code was placed in the public domain by its original author,
|
|
12
|
+
* Stefan Gustavson. You may use it as you see fit, but
|
|
13
|
+
* attribution is appreciated.
|
|
14
|
+
*
|
|
15
|
+
* Updated to ES modules by [Guinetik] in 2025
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
export class Noise {
|
|
19
|
+
// Internal helper class for gradient calculations
|
|
20
|
+
static #Grad = class {
|
|
21
|
+
constructor(x, y, z) {
|
|
22
|
+
this.x = x;
|
|
23
|
+
this.y = y;
|
|
24
|
+
this.z = z;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
dot2(x, y) {
|
|
28
|
+
return this.x * x + this.y * y;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
dot3(x, y, z) {
|
|
32
|
+
return this.x * x + this.y * y + this.z * z;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
// Pre-computed gradients
|
|
37
|
+
static #grad3 = [
|
|
38
|
+
new this.#Grad(1, 1, 0),
|
|
39
|
+
new this.#Grad(-1, 1, 0),
|
|
40
|
+
new this.#Grad(1, -1, 0),
|
|
41
|
+
new this.#Grad(-1, -1, 0),
|
|
42
|
+
new this.#Grad(1, 0, 1),
|
|
43
|
+
new this.#Grad(-1, 0, 1),
|
|
44
|
+
new this.#Grad(1, 0, -1),
|
|
45
|
+
new this.#Grad(-1, 0, -1),
|
|
46
|
+
new this.#Grad(0, 1, 1),
|
|
47
|
+
new this.#Grad(0, -1, 1),
|
|
48
|
+
new this.#Grad(0, 1, -1),
|
|
49
|
+
new this.#Grad(0, -1, -1),
|
|
50
|
+
];
|
|
51
|
+
|
|
52
|
+
// Permutation table
|
|
53
|
+
static #p = [
|
|
54
|
+
151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225, 140,
|
|
55
|
+
36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148, 247, 120,
|
|
56
|
+
234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32, 57, 177, 33,
|
|
57
|
+
88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175, 74, 165, 71,
|
|
58
|
+
134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122, 60, 211, 133,
|
|
59
|
+
230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54, 65, 25, 63, 161,
|
|
60
|
+
1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169, 200, 196, 135, 130,
|
|
61
|
+
116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64, 52, 217, 226, 250,
|
|
62
|
+
124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212, 207, 206, 59, 227,
|
|
63
|
+
47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213, 119, 248, 152, 2, 44,
|
|
64
|
+
154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9, 129, 22, 39, 253, 19, 98,
|
|
65
|
+
108, 110, 79, 113, 224, 232, 178, 185, 112, 104, 218, 246, 97, 228, 251, 34,
|
|
66
|
+
242, 193, 238, 210, 144, 12, 191, 179, 162, 241, 81, 51, 145, 235, 249, 14,
|
|
67
|
+
239, 107, 49, 192, 214, 31, 181, 199, 106, 157, 184, 84, 204, 176, 115, 121,
|
|
68
|
+
50, 45, 127, 4, 150, 254, 138, 236, 205, 93, 222, 114, 67, 29, 24, 72, 243,
|
|
69
|
+
141, 128, 195, 78, 66, 215, 61, 156, 180,
|
|
70
|
+
];
|
|
71
|
+
|
|
72
|
+
// To remove the need for index wrapping, double the permutation table length
|
|
73
|
+
static #perm = new Array(512);
|
|
74
|
+
static #gradP = new Array(512);
|
|
75
|
+
|
|
76
|
+
// Skewing and unskewing factors
|
|
77
|
+
static #F2 = 0.5 * (Math.sqrt(3) - 1);
|
|
78
|
+
static #G2 = (3 - Math.sqrt(3)) / 6;
|
|
79
|
+
|
|
80
|
+
static #F3 = 1 / 3;
|
|
81
|
+
static #G3 = 1 / 6;
|
|
82
|
+
|
|
83
|
+
// Helper functions
|
|
84
|
+
static #fade(t) {
|
|
85
|
+
return t * t * t * (t * (t * 6 - 15) + 10);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
static #lerp(a, b, t) {
|
|
89
|
+
return (1 - t) * a + t * b;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// Initialize with default seed
|
|
93
|
+
static {
|
|
94
|
+
this.seed(0);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Seed the noise function
|
|
99
|
+
* @param {number} seed - A seed value between 0 and 65535
|
|
100
|
+
*/
|
|
101
|
+
static seed(seed) {
|
|
102
|
+
if (seed > 0 && seed < 1) {
|
|
103
|
+
// Scale the seed out
|
|
104
|
+
seed *= 65536;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
seed = Math.floor(seed);
|
|
108
|
+
if (seed < 256) {
|
|
109
|
+
seed |= seed << 8;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
for (let i = 0; i < 256; i++) {
|
|
113
|
+
let v;
|
|
114
|
+
if (i & 1) {
|
|
115
|
+
v = this.#p[i] ^ (seed & 255);
|
|
116
|
+
} else {
|
|
117
|
+
v = this.#p[i] ^ ((seed >> 8) & 255);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
this.#perm[i] = this.#perm[i + 256] = v;
|
|
121
|
+
this.#gradP[i] = this.#gradP[i + 256] = this.#grad3[v % 12];
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* 2D simplex noise
|
|
127
|
+
* @param {number} xin - X coordinate
|
|
128
|
+
* @param {number} yin - Y coordinate
|
|
129
|
+
* @returns {number} Noise value in range [-1, 1]
|
|
130
|
+
*/
|
|
131
|
+
static simplex2(xin, yin) {
|
|
132
|
+
let n0, n1, n2; // Noise contributions from the three corners
|
|
133
|
+
// Skew the input space to determine which simplex cell we're in
|
|
134
|
+
const s = (xin + yin) * this.#F2; // Hairy factor for 2D
|
|
135
|
+
const i = Math.floor(xin + s);
|
|
136
|
+
const j = Math.floor(yin + s);
|
|
137
|
+
const t = (i + j) * this.#G2;
|
|
138
|
+
const x0 = xin - i + t; // The x,y distances from the cell origin, unskewed.
|
|
139
|
+
const y0 = yin - j + t;
|
|
140
|
+
// For the 2D case, the simplex shape is an equilateral triangle.
|
|
141
|
+
// Determine which simplex we are in.
|
|
142
|
+
let i1, j1; // Offsets for second (middle) corner of simplex in (i,j) coords
|
|
143
|
+
if (x0 > y0) {
|
|
144
|
+
// lower triangle, XY order: (0,0)->(1,0)->(1,1)
|
|
145
|
+
i1 = 1;
|
|
146
|
+
j1 = 0;
|
|
147
|
+
} else {
|
|
148
|
+
// upper triangle, YX order: (0,0)->(0,1)->(1,1)
|
|
149
|
+
i1 = 0;
|
|
150
|
+
j1 = 1;
|
|
151
|
+
}
|
|
152
|
+
// A step of (1,0) in (i,j) means a step of (1-c,-c) in (x,y), and
|
|
153
|
+
// a step of (0,1) in (i,j) means a step of (-c,1-c) in (x,y), where
|
|
154
|
+
// c = (3-sqrt(3))/6
|
|
155
|
+
const x1 = x0 - i1 + this.#G2; // Offsets for middle corner in (x,y) unskewed coords
|
|
156
|
+
const y1 = y0 - j1 + this.#G2;
|
|
157
|
+
const x2 = x0 - 1 + 2 * this.#G2; // Offsets for last corner in (x,y) unskewed coords
|
|
158
|
+
const y2 = y0 - 1 + 2 * this.#G2;
|
|
159
|
+
// Work out the hashed gradient indices of the three simplex corners
|
|
160
|
+
const ii = i & 255;
|
|
161
|
+
const jj = j & 255;
|
|
162
|
+
const gi0 = this.#gradP[ii + this.#perm[jj]];
|
|
163
|
+
const gi1 = this.#gradP[ii + i1 + this.#perm[jj + j1]];
|
|
164
|
+
const gi2 = this.#gradP[ii + 1 + this.#perm[jj + 1]];
|
|
165
|
+
// Calculate the contribution from the three corners
|
|
166
|
+
let t0 = 0.5 - x0 * x0 - y0 * y0;
|
|
167
|
+
if (t0 < 0) {
|
|
168
|
+
n0 = 0;
|
|
169
|
+
} else {
|
|
170
|
+
t0 *= t0;
|
|
171
|
+
n0 = t0 * t0 * gi0.dot2(x0, y0); // (x,y) of grad3 used for 2D gradient
|
|
172
|
+
}
|
|
173
|
+
let t1 = 0.5 - x1 * x1 - y1 * y1;
|
|
174
|
+
if (t1 < 0) {
|
|
175
|
+
n1 = 0;
|
|
176
|
+
} else {
|
|
177
|
+
t1 *= t1;
|
|
178
|
+
n1 = t1 * t1 * gi1.dot2(x1, y1);
|
|
179
|
+
}
|
|
180
|
+
let t2 = 0.5 - x2 * x2 - y2 * y2;
|
|
181
|
+
if (t2 < 0) {
|
|
182
|
+
n2 = 0;
|
|
183
|
+
} else {
|
|
184
|
+
t2 *= t2;
|
|
185
|
+
n2 = t2 * t2 * gi2.dot2(x2, y2);
|
|
186
|
+
}
|
|
187
|
+
// Add contributions from each corner to get the final noise value.
|
|
188
|
+
// The result is scaled to return values in the interval [-1,1].
|
|
189
|
+
return 70 * (n0 + n1 + n2);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* 3D simplex noise
|
|
194
|
+
* @param {number} xin - X coordinate
|
|
195
|
+
* @param {number} yin - Y coordinate
|
|
196
|
+
* @param {number} zin - Z coordinate
|
|
197
|
+
* @returns {number} Noise value in range [-1, 1]
|
|
198
|
+
*/
|
|
199
|
+
static simplex3(xin, yin, zin) {
|
|
200
|
+
let n0, n1, n2, n3; // Noise contributions from the four corners
|
|
201
|
+
|
|
202
|
+
// Skew the input space to determine which simplex cell we're in
|
|
203
|
+
const s = (xin + yin + zin) * this.#F3; // Hairy factor for 2D
|
|
204
|
+
const i = Math.floor(xin + s);
|
|
205
|
+
const j = Math.floor(yin + s);
|
|
206
|
+
const k = Math.floor(zin + s);
|
|
207
|
+
|
|
208
|
+
const t = (i + j + k) * this.#G3;
|
|
209
|
+
const x0 = xin - i + t; // The x,y distances from the cell origin, unskewed.
|
|
210
|
+
const y0 = yin - j + t;
|
|
211
|
+
const z0 = zin - k + t;
|
|
212
|
+
|
|
213
|
+
// For the 3D case, the simplex shape is a slightly irregular tetrahedron.
|
|
214
|
+
// Determine which simplex we are in.
|
|
215
|
+
let i1, j1, k1; // Offsets for second corner of simplex in (i,j,k) coords
|
|
216
|
+
let i2, j2, k2; // Offsets for third corner of simplex in (i,j,k) coords
|
|
217
|
+
if (x0 >= y0) {
|
|
218
|
+
if (y0 >= z0) {
|
|
219
|
+
i1 = 1;
|
|
220
|
+
j1 = 0;
|
|
221
|
+
k1 = 0;
|
|
222
|
+
i2 = 1;
|
|
223
|
+
j2 = 1;
|
|
224
|
+
k2 = 0;
|
|
225
|
+
} else if (x0 >= z0) {
|
|
226
|
+
i1 = 1;
|
|
227
|
+
j1 = 0;
|
|
228
|
+
k1 = 0;
|
|
229
|
+
i2 = 1;
|
|
230
|
+
j2 = 0;
|
|
231
|
+
k2 = 1;
|
|
232
|
+
} else {
|
|
233
|
+
i1 = 0;
|
|
234
|
+
j1 = 0;
|
|
235
|
+
k1 = 1;
|
|
236
|
+
i2 = 1;
|
|
237
|
+
j2 = 0;
|
|
238
|
+
k2 = 1;
|
|
239
|
+
}
|
|
240
|
+
} else {
|
|
241
|
+
if (y0 < z0) {
|
|
242
|
+
i1 = 0;
|
|
243
|
+
j1 = 0;
|
|
244
|
+
k1 = 1;
|
|
245
|
+
i2 = 0;
|
|
246
|
+
j2 = 1;
|
|
247
|
+
k2 = 1;
|
|
248
|
+
} else if (x0 < z0) {
|
|
249
|
+
i1 = 0;
|
|
250
|
+
j1 = 1;
|
|
251
|
+
k1 = 0;
|
|
252
|
+
i2 = 0;
|
|
253
|
+
j2 = 1;
|
|
254
|
+
k2 = 1;
|
|
255
|
+
} else {
|
|
256
|
+
i1 = 0;
|
|
257
|
+
j1 = 1;
|
|
258
|
+
k1 = 0;
|
|
259
|
+
i2 = 1;
|
|
260
|
+
j2 = 1;
|
|
261
|
+
k2 = 0;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// A step of (1,0,0) in (i,j,k) means a step of (1-c,-c,-c) in (x,y,z),
|
|
266
|
+
// a step of (0,1,0) in (i,j,k) means a step of (-c,1-c,-c) in (x,y,z), and
|
|
267
|
+
// a step of (0,0,1) in (i,j,k) means a step of (-c,-c,1-c) in (x,y,z), where
|
|
268
|
+
// c = 1/6.
|
|
269
|
+
const x1 = x0 - i1 + this.#G3; // Offsets for second corner
|
|
270
|
+
const y1 = y0 - j1 + this.#G3;
|
|
271
|
+
const z1 = z0 - k1 + this.#G3;
|
|
272
|
+
|
|
273
|
+
const x2 = x0 - i2 + 2 * this.#G3; // Offsets for third corner
|
|
274
|
+
const y2 = y0 - j2 + 2 * this.#G3;
|
|
275
|
+
const z2 = z0 - k2 + 2 * this.#G3;
|
|
276
|
+
|
|
277
|
+
const x3 = x0 - 1 + 3 * this.#G3; // Offsets for fourth corner
|
|
278
|
+
const y3 = y0 - 1 + 3 * this.#G3;
|
|
279
|
+
const z3 = z0 - 1 + 3 * this.#G3;
|
|
280
|
+
|
|
281
|
+
// Work out the hashed gradient indices of the four simplex corners
|
|
282
|
+
const ii = i & 255;
|
|
283
|
+
const jj = j & 255;
|
|
284
|
+
const kk = k & 255;
|
|
285
|
+
const gi0 = this.#gradP[ii + this.#perm[jj + this.#perm[kk]]];
|
|
286
|
+
const gi1 =
|
|
287
|
+
this.#gradP[ii + i1 + this.#perm[jj + j1 + this.#perm[kk + k1]]];
|
|
288
|
+
const gi2 =
|
|
289
|
+
this.#gradP[ii + i2 + this.#perm[jj + j2 + this.#perm[kk + k2]]];
|
|
290
|
+
const gi3 = this.#gradP[ii + 1 + this.#perm[jj + 1 + this.#perm[kk + 1]]];
|
|
291
|
+
|
|
292
|
+
// Calculate the contribution from the four corners
|
|
293
|
+
let t0 = 0.6 - x0 * x0 - y0 * y0 - z0 * z0;
|
|
294
|
+
if (t0 < 0) {
|
|
295
|
+
n0 = 0;
|
|
296
|
+
} else {
|
|
297
|
+
t0 *= t0;
|
|
298
|
+
n0 = t0 * t0 * gi0.dot3(x0, y0, z0); // (x,y) of grad3 used for 2D gradient
|
|
299
|
+
}
|
|
300
|
+
let t1 = 0.6 - x1 * x1 - y1 * y1 - z1 * z1;
|
|
301
|
+
if (t1 < 0) {
|
|
302
|
+
n1 = 0;
|
|
303
|
+
} else {
|
|
304
|
+
t1 *= t1;
|
|
305
|
+
n1 = t1 * t1 * gi1.dot3(x1, y1, z1);
|
|
306
|
+
}
|
|
307
|
+
let t2 = 0.6 - x2 * x2 - y2 * y2 - z2 * z2;
|
|
308
|
+
if (t2 < 0) {
|
|
309
|
+
n2 = 0;
|
|
310
|
+
} else {
|
|
311
|
+
t2 *= t2;
|
|
312
|
+
n2 = t2 * t2 * gi2.dot3(x2, y2, z2);
|
|
313
|
+
}
|
|
314
|
+
let t3 = 0.6 - x3 * x3 - y3 * y3 - z3 * z3;
|
|
315
|
+
if (t3 < 0) {
|
|
316
|
+
n3 = 0;
|
|
317
|
+
} else {
|
|
318
|
+
t3 *= t3;
|
|
319
|
+
n3 = t3 * t3 * gi3.dot3(x3, y3, z3);
|
|
320
|
+
}
|
|
321
|
+
// Add contributions from each corner to get the final noise value.
|
|
322
|
+
// The result is scaled to return values in the interval [-1,1].
|
|
323
|
+
return 32 * (n0 + n1 + n2 + n3);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* 2D Perlin Noise
|
|
328
|
+
* @param {number} x - X coordinate
|
|
329
|
+
* @param {number} y - Y coordinate
|
|
330
|
+
* @returns {number} Noise value in range [-1, 1]
|
|
331
|
+
*/
|
|
332
|
+
static perlin2(x, y) {
|
|
333
|
+
// Find unit grid cell containing point
|
|
334
|
+
const X = Math.floor(x),
|
|
335
|
+
Y = Math.floor(y);
|
|
336
|
+
// Get relative xy coordinates of point within that cell
|
|
337
|
+
x = x - X;
|
|
338
|
+
y = y - Y;
|
|
339
|
+
// Wrap the integer cells at 255 (smaller integer period can be introduced here)
|
|
340
|
+
const XX = X & 255,
|
|
341
|
+
YY = Y & 255;
|
|
342
|
+
|
|
343
|
+
// Calculate noise contributions from each of the four corners
|
|
344
|
+
const n00 = this.#gradP[XX + this.#perm[YY]].dot2(x, y);
|
|
345
|
+
const n01 = this.#gradP[XX + this.#perm[YY + 1]].dot2(x, y - 1);
|
|
346
|
+
const n10 = this.#gradP[XX + 1 + this.#perm[YY]].dot2(x - 1, y);
|
|
347
|
+
const n11 = this.#gradP[XX + 1 + this.#perm[YY + 1]].dot2(x - 1, y - 1);
|
|
348
|
+
|
|
349
|
+
// Compute the fade curve value for x
|
|
350
|
+
const u = this.#fade(x);
|
|
351
|
+
|
|
352
|
+
// Interpolate the four results
|
|
353
|
+
return this.#lerp(
|
|
354
|
+
this.#lerp(n00, n10, u),
|
|
355
|
+
this.#lerp(n01, n11, u),
|
|
356
|
+
this.#fade(y)
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* 3D Perlin Noise
|
|
362
|
+
* @param {number} x - X coordinate
|
|
363
|
+
* @param {number} y - Y coordinate
|
|
364
|
+
* @param {number} z - Z coordinate
|
|
365
|
+
* @returns {number} Noise value in range [-1, 1]
|
|
366
|
+
*/
|
|
367
|
+
static perlin3(x, y, z) {
|
|
368
|
+
// Find unit grid cell containing point
|
|
369
|
+
const X = Math.floor(x),
|
|
370
|
+
Y = Math.floor(y),
|
|
371
|
+
Z = Math.floor(z);
|
|
372
|
+
// Get relative xyz coordinates of point within that cell
|
|
373
|
+
x = x - X;
|
|
374
|
+
y = y - Y;
|
|
375
|
+
z = z - Z;
|
|
376
|
+
// Wrap the integer cells at 255 (smaller integer period can be introduced here)
|
|
377
|
+
const XX = X & 255,
|
|
378
|
+
YY = Y & 255,
|
|
379
|
+
ZZ = Z & 255;
|
|
380
|
+
|
|
381
|
+
// Calculate noise contributions from each of the eight corners
|
|
382
|
+
const n000 = this.#gradP[XX + this.#perm[YY + this.#perm[ZZ]]].dot3(
|
|
383
|
+
x,
|
|
384
|
+
y,
|
|
385
|
+
z
|
|
386
|
+
);
|
|
387
|
+
const n001 = this.#gradP[XX + this.#perm[YY + this.#perm[ZZ + 1]]].dot3(
|
|
388
|
+
x,
|
|
389
|
+
y,
|
|
390
|
+
z - 1
|
|
391
|
+
);
|
|
392
|
+
const n010 = this.#gradP[XX + this.#perm[YY + 1 + this.#perm[ZZ]]].dot3(
|
|
393
|
+
x,
|
|
394
|
+
y - 1,
|
|
395
|
+
z
|
|
396
|
+
);
|
|
397
|
+
const n011 = this.#gradP[XX + this.#perm[YY + 1 + this.#perm[ZZ + 1]]].dot3(
|
|
398
|
+
x,
|
|
399
|
+
y - 1,
|
|
400
|
+
z - 1
|
|
401
|
+
);
|
|
402
|
+
const n100 = this.#gradP[XX + 1 + this.#perm[YY + this.#perm[ZZ]]].dot3(
|
|
403
|
+
x - 1,
|
|
404
|
+
y,
|
|
405
|
+
z
|
|
406
|
+
);
|
|
407
|
+
const n101 = this.#gradP[XX + 1 + this.#perm[YY + this.#perm[ZZ + 1]]].dot3(
|
|
408
|
+
x - 1,
|
|
409
|
+
y,
|
|
410
|
+
z - 1
|
|
411
|
+
);
|
|
412
|
+
const n110 = this.#gradP[XX + 1 + this.#perm[YY + 1 + this.#perm[ZZ]]].dot3(
|
|
413
|
+
x - 1,
|
|
414
|
+
y - 1,
|
|
415
|
+
z
|
|
416
|
+
);
|
|
417
|
+
const n111 = this.#gradP[
|
|
418
|
+
XX + 1 + this.#perm[YY + 1 + this.#perm[ZZ + 1]]
|
|
419
|
+
].dot3(x - 1, y - 1, z - 1);
|
|
420
|
+
|
|
421
|
+
// Compute the fade curve value for x, y, z
|
|
422
|
+
const u = this.#fade(x);
|
|
423
|
+
const v = this.#fade(y);
|
|
424
|
+
const w = this.#fade(z);
|
|
425
|
+
|
|
426
|
+
// Interpolate
|
|
427
|
+
return this.#lerp(
|
|
428
|
+
this.#lerp(this.#lerp(n000, n100, u), this.#lerp(n001, n101, u), w),
|
|
429
|
+
this.#lerp(this.#lerp(n010, n110, u), this.#lerp(n011, n111, u), w),
|
|
430
|
+
v
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
}
|
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Orbital mechanics utilities for geodesic motion visualization.
|
|
3
|
+
* Provides functions for Keplerian motion and GR corrections.
|
|
4
|
+
*
|
|
5
|
+
* All functions are pure - can be refactored to a class later if needed.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* import { keplerianOmega, schwarzschildPrecessionRate } from './orbital.js';
|
|
9
|
+
*
|
|
10
|
+
* // Base angular velocity
|
|
11
|
+
* const omega = keplerianOmega(10, 1, 0.5);
|
|
12
|
+
*
|
|
13
|
+
* // GR precession correction
|
|
14
|
+
* const precession = schwarzschildPrecessionRate(10, 2, 0.15);
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
18
|
+
// ANGULAR VELOCITY
|
|
19
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Keplerian angular velocity based on Kepler's 3rd law.
|
|
23
|
+
*
|
|
24
|
+
* omega ∝ sqrt(M) / r^(3/2)
|
|
25
|
+
*
|
|
26
|
+
* The referenceR parameter allows scaling for visualization - objects at
|
|
27
|
+
* r = referenceR will have angular velocity = speedFactor * sqrt(M).
|
|
28
|
+
*
|
|
29
|
+
* @param {number} r - Orbital radius
|
|
30
|
+
* @param {number} M - Central mass (geometrized units)
|
|
31
|
+
* @param {number} [speedFactor=1] - Speed multiplier for visualization
|
|
32
|
+
* @param {number} [referenceR=5] - Reference radius for scaling
|
|
33
|
+
* @returns {number} Angular velocity omega
|
|
34
|
+
*/
|
|
35
|
+
export function keplerianOmega(r, M, speedFactor = 1, referenceR = 5) {
|
|
36
|
+
if (r <= 0) return 0;
|
|
37
|
+
return (speedFactor * Math.sqrt(M)) / Math.pow(r / referenceR, 1.5);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
41
|
+
// GR PRECESSION RATES
|
|
42
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* GR orbital precession rate for Schwarzschild spacetime.
|
|
46
|
+
*
|
|
47
|
+
* In GR, orbits don't close - they precess. The rate scales as rs/r,
|
|
48
|
+
* meaning closer orbits precess faster.
|
|
49
|
+
*
|
|
50
|
+
* The exact formula is Δφ ≈ 6πM/a(1-e²) per orbit, but for visualization
|
|
51
|
+
* we use a simpler form that captures the essential 1/r dependence.
|
|
52
|
+
*
|
|
53
|
+
* @param {number} r - Orbital radius
|
|
54
|
+
* @param {number} rs - Schwarzschild radius (2M)
|
|
55
|
+
* @param {number} [factor=1] - Precession rate multiplier
|
|
56
|
+
* @returns {number} Precession rate (multiply by dt for angle change)
|
|
57
|
+
*/
|
|
58
|
+
export function schwarzschildPrecessionRate(r, rs, factor = 1) {
|
|
59
|
+
if (r <= rs) return 0;
|
|
60
|
+
return factor * (rs / r);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* GR orbital precession rate for Kerr spacetime.
|
|
65
|
+
*
|
|
66
|
+
* Includes additional contribution from frame dragging.
|
|
67
|
+
* Prograde orbits precess faster than in Schwarzschild.
|
|
68
|
+
*
|
|
69
|
+
* @param {number} r - Orbital radius
|
|
70
|
+
* @param {number} M - Mass parameter
|
|
71
|
+
* @param {number} a - Spin parameter (0 to M)
|
|
72
|
+
* @param {number} [factor=1] - Precession rate multiplier
|
|
73
|
+
* @returns {number} Precession rate
|
|
74
|
+
*/
|
|
75
|
+
export function kerrPrecessionRate(r, M, a, factor = 1) {
|
|
76
|
+
const rs = 2 * M;
|
|
77
|
+
if (r <= rs) return 0;
|
|
78
|
+
// Base Schwarzschild precession + frame dragging enhancement
|
|
79
|
+
return factor * (rs / r) * (1 + a / M);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
83
|
+
// ORBITAL GEOMETRY
|
|
84
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Compute orbital radius with eccentricity (Keplerian ellipse).
|
|
88
|
+
*
|
|
89
|
+
* r(φ) = a(1 - e²) / (1 + e*cos(φ))
|
|
90
|
+
*
|
|
91
|
+
* For small eccentricity, this simplifies to approximately:
|
|
92
|
+
* r ≈ a + a*e*sin(φ) (used in demos for smooth oscillation)
|
|
93
|
+
*
|
|
94
|
+
* @param {number} semiMajor - Semi-major axis a
|
|
95
|
+
* @param {number} eccentricity - Orbital eccentricity e (0 to 1)
|
|
96
|
+
* @param {number} phi - True anomaly (orbital angle)
|
|
97
|
+
* @returns {number} Orbital radius at angle phi
|
|
98
|
+
*/
|
|
99
|
+
export function orbitalRadius(semiMajor, eccentricity, phi) {
|
|
100
|
+
if (eccentricity >= 1) return semiMajor;
|
|
101
|
+
const p = semiMajor * (1 - eccentricity * eccentricity);
|
|
102
|
+
return p / (1 + eccentricity * Math.cos(phi));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Simplified radial oscillation for small eccentricity.
|
|
107
|
+
* More visually smooth than true Keplerian ellipse.
|
|
108
|
+
*
|
|
109
|
+
* @param {number} semiMajor - Base orbital radius
|
|
110
|
+
* @param {number} eccentricity - Eccentricity (small values)
|
|
111
|
+
* @param {number} phi - Orbital angle
|
|
112
|
+
* @param {number} [amplitudeFactor=2] - Oscillation amplitude multiplier
|
|
113
|
+
* @returns {number} Orbital radius
|
|
114
|
+
*/
|
|
115
|
+
export function orbitalRadiusSimple(semiMajor, eccentricity, phi, amplitudeFactor = 2) {
|
|
116
|
+
const oscillation = eccentricity * Math.sin(phi * 2);
|
|
117
|
+
return semiMajor + oscillation * amplitudeFactor;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Decaying orbital radius.
|
|
122
|
+
* Applies a decay factor to the orbital radius over time/angle.
|
|
123
|
+
*
|
|
124
|
+
* @param {number} r0 - Initial orbital radius
|
|
125
|
+
* @param {number} decayFactor - How fast the orbit decays (0 to 1)
|
|
126
|
+
* @param {number} t - Time or progress factor
|
|
127
|
+
* @returns {number} Decayed radius
|
|
128
|
+
*/
|
|
129
|
+
export function decayingOrbitalRadius(r0, decayFactor, t) {
|
|
130
|
+
return r0 * Math.exp(-decayFactor * t);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Computes a terminal trajectory (direct fall).
|
|
135
|
+
* Interpolates between a starting point and the center (0,0,0).
|
|
136
|
+
*
|
|
137
|
+
* @param {number} startX - Start X
|
|
138
|
+
* @param {number} startY - Start Y
|
|
139
|
+
* @param {number} startZ - Start Z
|
|
140
|
+
* @param {number} progress - Progress (0 to 1)
|
|
141
|
+
* @param {Function} easingFn - Optional easing function
|
|
142
|
+
* @returns {Object} Position { x, y, z }
|
|
143
|
+
*/
|
|
144
|
+
export function getTerminalTrajectory(startX, startY, startZ, progress, easingFn = null) {
|
|
145
|
+
const t = easingFn ? easingFn(progress) : progress;
|
|
146
|
+
return {
|
|
147
|
+
x: startX * (1 - t),
|
|
148
|
+
y: startY * (1 - t),
|
|
149
|
+
z: startZ * (1 - t),
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
154
|
+
// TRAIL MANAGEMENT
|
|
155
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Add a point to an orbital trail array, maintaining max length.
|
|
159
|
+
*
|
|
160
|
+
* Points are added at the front (newest first) for efficient rendering
|
|
161
|
+
* of fading trails.
|
|
162
|
+
*
|
|
163
|
+
* @param {Array} trail - Trail array (modified in place)
|
|
164
|
+
* @param {Object} point - Point to add { x, z, r, ... }
|
|
165
|
+
* @param {number} [maxLength=80] - Maximum trail length
|
|
166
|
+
* @returns {Array} The modified trail array
|
|
167
|
+
*/
|
|
168
|
+
export function updateTrail(trail, point, maxLength = 80) {
|
|
169
|
+
trail.unshift(point);
|
|
170
|
+
if (trail.length > maxLength) {
|
|
171
|
+
trail.pop();
|
|
172
|
+
}
|
|
173
|
+
return trail;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Create a trail point from orbital state.
|
|
178
|
+
*
|
|
179
|
+
* @param {number} r - Orbital radius
|
|
180
|
+
* @param {number} phi - Orbital angle (including precession)
|
|
181
|
+
* @param {Object} [extra={}] - Additional data to include
|
|
182
|
+
* @returns {Object} Trail point { x, z, r, ...extra }
|
|
183
|
+
*/
|
|
184
|
+
export function createTrailPoint(r, phi, extra = {}) {
|
|
185
|
+
return {
|
|
186
|
+
x: Math.cos(phi) * r,
|
|
187
|
+
z: Math.sin(phi) * r,
|
|
188
|
+
r,
|
|
189
|
+
...extra,
|
|
190
|
+
};
|
|
191
|
+
}
|