{
replay;
const scene = new THREE.Scene();
const [[w, animate, particleSize], [sigma, beta, rho]] = values;
if (!animate) {
const controls = new THREE.OrbitControls(camera, renderer.domElement);
invalidation.then(() => (controls.dispose(), renderer.dispose()));
controls.addEventListener("change", () => renderer.render(scene, camera));
}
const geometry = new THREE.BufferGeometry();
geometry.setAttribute(
'position',
new THREE.Float32BufferAttribute(startPositions, 3)
);
const material = new THREE.PointsMaterial({
size: particleSize,
color: 0xffffff,
transparent: true,
opacity: 0.2
});
const points = new THREE.Points(geometry, material);
points.position.z = -Math.sqrt(w);
scene.add(points);
let t = 0;
const dt = 0.01;
const positions = points.geometry.attributes.position.array;
while (true) {
t += dt;
await Promises.delay(10);
if (animate) {
camera.lookAt(new THREE.Vector3(0, 0, 0));
camera.position.x = Math.sin(t / 2) * camOffset;
camera.position.z = Math.cos(t / 2) * camOffset;
}
for (let i = 0; i < positions.length; ++i) {
if (i % 3 === 0) {
const dx = sigma * (positions[i + 1] - positions[i]) * dt;
positions[i] += dx;
}
if (i % 3 === 1) {
const dy =
(positions[i - 1] * (rho - positions[i + 1]) - positions[i]) * dt;
positions[i] += dy;
}
if (i % 3 === 2) {
const dz =
(positions[i - 2] * positions[i - 1] - beta * positions[i]) * dt;
positions[i] += dz;
}
}
points.geometry.attributes.position.needsUpdate = true;
renderer.render(scene, camera);
yield renderer.domElement;
}
}