WebAssembly Code Generation
Generate WebAssembly (WASM) for browser-based physics simulations.
Overview
WebAssembly enables near-native performance in web browsers, making it ideal for:
Interactive physics demonstrations
Educational web applications
Browser-based games with realistic physics
Online simulation tools
Note
WebAssembly support is experimental. Basic mechanics simulations work, but SPH fluid dynamics require additional browser features.
Prerequisites
To generate and use WebAssembly:
Emscripten SDK: Install from https://emscripten.org
Modern browser: Chrome, Firefox, Safari, or Edge (recent versions)
# Install Emscripten
git clone https://github.com/emscripten-core/emsdk.git
cd emsdk
./emsdk install latest
./emsdk activate latest
source ./emsdk_env.sh
Basic Usage
from mechanics_dsl import PhysicsCompiler
compiler = PhysicsCompiler()
compiler.compile_dsl(source)
# Generate WebAssembly
compiler.compile_to_wasm("pendulum.wasm")
This generates:
pendulum.wasm: WebAssembly binarypendulum.js: JavaScript glue codependulum.html: Simple test page (optional)
Using in Web Pages
Basic HTML integration:
<!DOCTYPE html>
<html>
<head>
<script src="pendulum.js"></script>
</head>
<body>
<canvas id="canvas" width="800" height="600"></canvas>
<script>
Module.onRuntimeInitialized = function() {
// Initialize simulation
const sim = Module._create_simulation();
// Animation loop
function animate() {
Module._step_simulation(sim, 0.016); // 60 FPS
const state = Module._get_state(sim);
// Draw to canvas
drawPendulum(state);
requestAnimationFrame(animate);
}
animate();
};
</script>
</body>
</html>
JavaScript API
The generated JavaScript module provides:
// Create simulation instance
const sim = Module._create_simulation();
// Set initial conditions
Module._set_state(sim, theta, theta_dot);
// Step forward in time
Module._step_simulation(sim, dt);
// Get current state
const state = Module._get_state(sim);
// Returns: { theta: ..., theta_dot: ..., t: ... }
// Clean up
Module._destroy_simulation(sim);
Performance
WebAssembly typically achieves:
80-90% of native C++ performance
Much faster than equivalent JavaScript
Consistent across browsers
For physics simulations, expect:
System |
JavaScript (ms/step) |
WASM (ms/step) |
Speedup |
|---|---|---|---|
Pendulum |
0.5 |
0.05 |
10x |
Double pendulum |
2.0 |
0.15 |
13x |
N-body (10) |
15.0 |
1.2 |
12x |
Limitations
Current WebAssembly support has limitations:
No SPH fluids: Requires SIMD and threading (future)
No file I/O: Must use JavaScript for data export
Memory limits: Browser sandbox restricts memory
Debugging: Limited debugging tools compared to native
Future Plans
Planned WebAssembly enhancements:
SIMD support for SPH kernels
Web Workers for parallel simulation
WebGL integration for visualization
Interactive parameter controls
Example: Interactive Pendulum
Complete example with visualization:
<!DOCTYPE html>
<html>
<head>
<title>MechanicsDSL Pendulum</title>
<style>
canvas { border: 1px solid #333; }
.controls { margin: 10px 0; }
</style>
<script src="pendulum.js"></script>
</head>
<body>
<h1>Interactive Pendulum</h1>
<div class="controls">
<label>Angle: <input type="range" id="angle"
min="0" max="3.14" step="0.1" value="0.5"></label>
<button onclick="reset()">Reset</button>
</div>
<canvas id="canvas" width="400" height="400"></canvas>
<script>
let sim;
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
Module.onRuntimeInitialized = function() {
sim = Module._create_simulation();
animate();
};
function animate() {
Module._step_simulation(sim, 0.016);
draw();
requestAnimationFrame(animate);
}
function draw() {
const theta = Module._get_theta(sim);
const L = 150;
const cx = 200, cy = 100;
ctx.clearRect(0, 0, 400, 400);
// Draw rod
const x = cx + L * Math.sin(theta);
const y = cy + L * Math.cos(theta);
ctx.beginPath();
ctx.moveTo(cx, cy);
ctx.lineTo(x, y);
ctx.strokeStyle = '#333';
ctx.lineWidth = 3;
ctx.stroke();
// Draw bob
ctx.beginPath();
ctx.arc(x, y, 20, 0, 2 * Math.PI);
ctx.fillStyle = '#e63946';
ctx.fill();
}
function reset() {
const angle = document.getElementById('angle').value;
Module._set_state(sim, parseFloat(angle), 0);
}
</script>
</body>
</html>