nooshu - Matt Hobbs' Web Development Blog

Kneeling on the shoulders of giants

Category: Experiments

I’m constantly thinking of little projects to be working on to expand my knowledge and skill-set, posts relating are filed here.

Plotting the Lorenz Attractor using three.js

It’s been a while since I dabbled with three.js. There have been a few API changes, so it’s slightly different from what I remember. That being said it’s still as fun to use, and there are even a few API docs available (not sure if they are fully up to date though)! I happened to be reading an article on Chaos Theory and the “butterfly effect” which mentioned a lovely set of equations; the Lorenz Equations, also known as the Lorenz oscillator. So I decided to investigate further. Here they are in all their glory:

\begin{aligned}\dot{x} & = \sigma(y-x) \\ \dot{y} & = \rho x - y - xz \\ \dot{z} & = -\beta z + xy \end{aligned}

So what exactly is the Lorenz oscillator? Well to quote from Wikipedia “The Lorenz oscillator is a 3-dimensional dynamical system that exhibits chaotic flow, noted for its figure eight shape.”. What this really boils down to is how even very small change in the equations initial conditions (x, y and z) causes large changes over time, in a complex and non-repeating pattern. There’s a famous title of a talk given in 1972 by Philip Merilees:

Does the flap of a butterfly’s wings in Brazil set off a tornado in Texas?

The butterfly flapping its wings introduces slight changes to the initial conditions, creating a chain of events that lead to a tornado in Texas. The Lorenz butterfly is a graphical way of showing these changes over time on a much smaller scale.

I’ve created a demo that allows you to change variables related to the Lorenz butterfly and observe the effect it has on the system.

Example of my Lorenz attractor demo in action

Adjust the demo variables to see how the Lorenz butterfly changes.

There are a few variables you can play to change how the Lorenz attractor is rendered:

  • rhoValue: Called the Rayleigh number. Rho of value 28 shows chaotic behavior. Other values show periodic orbits.
  • showAxis: Allows you to turn the x, y, z (red, green, blue) axis on for reference.
  • randomStart: Picks a random initial conditions, rather than 0, 0, 0.
  • totalTime: The total time (or number of iterations performed) when generating the graph. Higher numbers equals more lines and increases the render time.
  • timeIncriment: The accuracy of the graph depends on the number of points plotted. A lower number creates a smoother graph but increases render time.
  • colorModifier: Simply changes the colo(u)r. Pointless but pretty!

While rendering a larger number of points, I noticed the browser lock-up for a second or so. This was because the points were being calculated on the browsers UI thread. Luckily modern browsers support thread like message passing in the form of the Web Workers API. By offloading the point calculation to its own thread (lorenzPoints.js), I was able to stop the nasty UI freeze. Unfortunately you are fairly limited with what you can pass back and forth between workers. It was possible to generate the three.js geometry in the worker thread thanks to the importScripts() method. I tried passing the three.js geometry back to the browser but all the methods were stripped out, leading to lots of errors (JSON issues). In the end I dropped back to calculating the points in the worker, pushing them into an array and generating the geometry on the main browser thread.

It was good fun dabbling with three.js, Web Workers and dat.gui again. Now on to my next project… View the demo here.

dat.gui – controller library for JavaScript

Very recently I’ve been looking at some awesome JavaScript experiments and have noticed they are all using the same GUI. Now I fully admit I had a little ‘blonde’ moment as I assumed it was just a style everyone had adopted; developers being ‘one of the cool kids’, that type of thing. It turns out I was wrong, and it finally clicked. All the experiments have started using a little controller library called dat.gui.

After it appeared on Google’s workshop (along with three.js), I thought it was about time I had a play with this neat little library. Luckily there’s an excellent set of documentation and working examples available so you can dive right in. Here’s a code example of how to get started:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
//Define the controller function
var FresnelControls = function() {
    this.movingParticles = 5000;
    this.seedColor = "#ff0098";
};

//Create the Dat.gui controls
var fc = new FresnelControls();

//Create the GUI
var gui = new dat.GUI();

//Add 2 folders
var f1 = gui.addFolder('Particle Dynamics');
var f2 = gui.addFolder('Particle Colours');
       
//Add the moving particles controller to folder 1
f1.add(fc, 'movingParticles', 0, 5000).step(1);

//Add the colour controller, store in a var to attach events
var seedColor = f2.addColor(fc, 'seedColor');

//Colour change event
seedColor.onChange(function(value) {
    //Do something on color change...
});

I decided to dig out an old demo I created last year and adapt it to use dat.gui. Originally I used jQuery + jQuery UI to control the JavaScript variables. It worked well, but it really added page weight (jQuery + UI came to over 90Kb); not great when you are only using it for the sliders.

Following the documentation you start off simple and progressively add more of the dat.gui functionality. You can see my adapted demo here. The dat.gui code is highlighted if you want to see how it was set up.

Dat.gui in action on the Euler Spiral demo I created.

You can see dat.gui in action on my modified Euler Spiral demo.

Dat.gui really has some excellent features available. I was able to make use of the colour picker, presets and folder functionality; but there’s a whole host of others I didn’t, such as the custom placement and updating the display automatically. Personally I love the presets functionality; supply the GUI with a little bit of JSON and away you go!

As always, a big thank you goes out to the Data Arts Team in Google’s Creative Lab for creating such a useful little library! One I will be using in every demo I create from now on.

Fun with Space Invaders and Parallax scrolling

Back when I was a young wippersnapper (many moons ago) one of my good friends had a Sega Mega Drive. As with any new console it was on every kids Christmas list but compared to the current generation of games consoles it looks very primitive. The games were immense fun and you didn’t need an instruction manual to play them. Two of my favourite games were Golden Axe and Sonic the Hedgehog. Sonic the Hedgehog used a technique called Parallax scrolling; this is where background images move slower than “closer” foreground images giving the illusion of depth in a 2D plane.

I’m quite late to the web parallax party as the effect was recreated and popularised back in 2008. I first remember seeing it being used by the holding page for Clearleft’s Silverback application, but it may have appeared elsewhere before that. Three years on the web is a long time and technology has moved on, so I set myself a little project to recreate the effect using the HTML5 canvas element.

Parallax scrolling using a Space Invaders alien

Move your mouse to see the Parallax scrolling effect.

To demonstrate the effect I used a few graphics from another iconic retro game: Space Invaders. As you move the mouse the scary alien separates into its constituent pixels. The foreground pixels move faster than the background pixels creating a slight parallax effect. You have three aliens to choose from: Dave, Julian and Brian, which I’ve named for no particular reason. I think the names quite suit them. I’ve also added a little randomness to the demo in how they are generated, which you can see by reloading the page.

Hooray for retro games and pointless demo’s! :)

Antimatter 3D Graph Plotter and a little animation

Last year I stumbled upon this blog post by @antimatter15 who added a little three line modification to mr.doobs particle floor demo and created a graph plotter in three.js. Unfortunately as three.js has developed and evolved the API has changed; in doing so it broke the graphing demo. I left a message asking if there was a fix on Antimatters blog but got no response. So I decided to update the code and fix it for the latest version of three.js; once updated for the latest API it ran as expected.

3D graph plotter using three.js

Antimatter15 graph plotter updated for latest version of three.js.

You pass the equation you wish to plot via a URL parameter and out the other pops a pretty 3D graph. Here are a couple of examples taken from the original blog post:

In updating the code I thought I’d have a little play myself and see if I could add a bit of motion to the graphs just for the fun of it. I’ve created a version of my own which you can view here.

Graphing multiple for formula using JavaScript and three.js

Modified version allows you to add more than one formula to plot.

In my version you no longer pass the formula you wish to plot via a URL parameter, you add it via the panel on the right hand side. You can add and remove as many equations as you wish and the demo will cycle between them. To do so update the right hand panel then click the “Plot new formula(e)” button. The equation that is currently being plotted is highlighted in grey and available mathematical functions listed below.

With a little bit of trial end error you can create some interesting effects. There may not be much practical use for the experiment but I enjoyed putting it together with a little help from mr.doob and antimatter15 :)

Debug Axes in three.js

Update: The code I had previously stopped working with the latest three.js API. I’ve updated and improved the code for the latest API.

I’ve been working on a couple of small projects using three.js recently; An issue I always seem to have when working with 3D is knowing the current orientation. To help me out I’ve put together a small snippet of JavaScript.

Creating a set of axis in three.js

{x: red, y: green, z: blue} It's not much to look at but the axes can be very useful.

The point where the lines cross is 0,0,0 as you’d expect, you can adjust the length of the line by changing the axisLength variable. I’ve uploaded a small demo so you can see the code used or copy / paste below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var debugaxis = function(axisLength){
    //Shorten the vertex function
    function v(x,y,z){
            return new THREE.Vertex(new THREE.Vector3(x,y,z));
    }
   
    //Create axis (point1, point2, colour)
    function createAxis(p1, p2, color){
            var line, lineGeometry = new THREE.Geometry(),
            lineMat = new THREE.LineBasicMaterial({color: color, lineWidth: 1});
            lineGeometry.vertices.push(p1, p2);
            line = new THREE.Line(lineGeometry, lineMat);
            scene.add(line);
    }
   
    createAxis(v(-axisLength, 0, 0), v(axisLength, 0, 0), 0xFF0000);
    createAxis(v(0, -axisLength, 0), v(0, axisLength, 0), 0x00FF00);
    createAxis(v(0, 0, -axisLength), v(0, 0, axisLength), 0x0000FF);
};

//To use enter the axis length
debugaxis(100);

It’s not much to look at, but it can certainly help you get your bearing when starting a new project (or when things aren’t working!). Hopefully you find it useful.

Currently on page 1 of 612345Last »