#!/usr/bin/env node // More involved particle system. Particles are persistent, we have a background // color, and the particles have a life cycle. Particles come and go slowly, going // through a period of brightness and a period of darkness. // Specify a layout file on the command line, or use the default (grid32x16z) var OPC = new require('./opc'); var model = OPC.loadModel(process.argv[2] || '../layouts/grid32x16z.json'); var client = new OPC('localhost', 7890); var totalLife = 300; var numParticles = 100; var zoom = 0.998; var intensity = -1.2; var backgroundHue = Math.random(); function newBloomTimer() { return Math.random() * 5000; } function randomPoint() { // A random point somewhere relevant on our model return [ 4 * (Math.random() - 0.5), 1 * (Math.random() - 0.5), 4 * (Math.random() - 0.5) ]; } // Start out with just a background var particles = [ { point: [], // Arbitrary location intensity: 1, // Unit intensity falloff: 0, // No falloff, particle has infinite size // Color is filled in later } ]; // Create other nascent particles that 'bloom' once a timer runs out for (var i = 0; i < numParticles; i++) { particles.push({ point: [0, 0, 0], intensity: 0, falloff: 30, color: OPC.hsv(Math.random(), 0.6, 0.8), bloomTimer: 20 + newBloomTimer() }) } function draw() { // Update background color backgroundHue = (backgroundHue + 0.0002) % 1; particles[0].color = OPC.hsv(backgroundHue, 0.8, 0.2); // Update particle state for (var i = 0; i < particles.length; i++) { var p = particles[i]; if (p.bloomTimer) { // Particle is blooming p.bloomTimer -= 1; if (p.bloomTimer <= 0) { // Done blooming. Start life cycle p.lifeTimer = totalLife; p.point = randomPoint(); p.bloomTimer = null; } } if (p.lifeTimer) { // Particle is alive. Update intensity. // Particles go through a life cycle with positive and negative intensity p.intensity = intensity * Math.sin(p.lifeTimer * 2 * Math.PI / totalLife); // Collapse into the center p.point[0] *= zoom; p.point[1] *= zoom; p.point[2] *= zoom; p.lifeTimer -= 1; if (p.lifeTimer <= 0) { // Particle is dead. Go back to blooming. p.bloomTimer = newBloomTimer(); p.lifeTimer = null; } } } client.mapParticles(particles, model); } setInterval(draw, 10);