Initial project setup: Rust/WASM solar system simulator with SvelteKit frontend
- Rust workspace with 4 crates: orbital-mechanics, mass-driver-core, mass-driver-wasm, mass-driver-backend - Keplerian orbital mechanics engine with JPL elements for 14 bodies (Sun, 8 planets, Pluto, Ceres, Europa, Titan, Ganymede) - Kepler equation solver and orbital position computation compiled to WASM - SvelteKit frontend with Tailwind CSS, Canvas2D renderer showing animated solar system - Orbit ellipses, planet dots with labels, Sun glow, grid, scale bar, pan/zoom controls - Time controls (play/pause, 5 speed levels, date picker) driving live simulation - 2D/3D view toggle (3D placeholder for Threlte integration) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
<script lang="ts">
|
||||
import { onMount, onDestroy } from 'svelte';
|
||||
import { SolarSystem2DRenderer } from '$lib/render/canvas2d/SolarSystem2D';
|
||||
import { simulation } from '$lib/stores/simulation.svelte';
|
||||
import { getBodyPositions, getBodyInfos, getOrbitPoints } from '$lib/wasm/bridge';
|
||||
|
||||
let canvas: HTMLCanvasElement;
|
||||
let renderer: SolarSystem2DRenderer;
|
||||
let animFrameId: number;
|
||||
let orbitsComputed = false;
|
||||
|
||||
function computeOrbits() {
|
||||
const bodyCount = simulation.bodyInfos.length;
|
||||
for (let i = 1; i < bodyCount; i++) {
|
||||
const points = getOrbitPoints(i, simulation.currentJD, 360);
|
||||
if (points.length > 0) {
|
||||
renderer.updateOrbit(i, points);
|
||||
}
|
||||
}
|
||||
orbitsComputed = true;
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
renderer = new SolarSystem2DRenderer(canvas);
|
||||
|
||||
if (simulation.wasmReady) {
|
||||
simulation.bodyInfos = getBodyInfos();
|
||||
}
|
||||
|
||||
let lastTime = performance.now();
|
||||
let frameCount = 0;
|
||||
|
||||
function mainLoop() {
|
||||
const now = performance.now();
|
||||
const dt = (now - lastTime) / 1000;
|
||||
lastTime = now;
|
||||
simulation.advanceTime(dt);
|
||||
|
||||
if (simulation.wasmReady) {
|
||||
simulation.bodyPositions = getBodyPositions(simulation.currentJD);
|
||||
renderer.updateBodies(simulation.bodyInfos, simulation.bodyPositions);
|
||||
|
||||
// Compute orbits on first frame and refresh every 600 frames (~10s)
|
||||
if (!orbitsComputed || frameCount % 600 === 0) {
|
||||
computeOrbits();
|
||||
}
|
||||
}
|
||||
renderer.render();
|
||||
frameCount++;
|
||||
animFrameId = requestAnimationFrame(mainLoop);
|
||||
}
|
||||
|
||||
mainLoop();
|
||||
});
|
||||
|
||||
onDestroy(() => {
|
||||
if (animFrameId) cancelAnimationFrame(animFrameId);
|
||||
renderer?.destroy();
|
||||
});
|
||||
</script>
|
||||
|
||||
<canvas
|
||||
bind:this={canvas}
|
||||
class="w-full h-full block"
|
||||
style="cursor: grab;"
|
||||
></canvas>
|
||||
Reference in New Issue
Block a user