define(['threejs'], function() {
    function initPreview($e, dims) {
        var w = 400; // XXX
        var h = 300; // XXX
        var renderer = new THREE.WebGLRenderer({
            clearAlpha: true
        });
        var camera = new THREE.PerspectiveCamera(45, w / h, 0.1, 10000);
        var scene = new THREE.Scene();

        scene.add(camera);
        camera.position.x = -50;
        camera.position.z = 400;
        renderer.setSize(w, h);

        var particles = initParticles(scene, dims);

        renderer.render(scene, camera);

        $e.append(renderer.domElement);

        $(window).on('resize', function() {
            // TODO: update w/h properly
            var w = 400;
            var h = 300;

            camera.aspect = w / h;
            camera.updateProjectionMatrix();

            renderer.setSize(w, h);
        });

        function execute(fn) {
            fn.forEach(function(op) {
                if(!op) return;

                var o = {
                    on: function() {
                        render(dims, particles, op.coords, 1);
                    },
                    off: function() {
                        render(dims, particles, op.coords, 0);
                    }
                }[op.op]();
            });

            renderer.render(scene, camera);
        }

        var prevTime;
        var ticks;
        function animate(init, cb) {
            var res = init;

            prevTime = new Date().getTime();
            ticks = 0;

            function anim() {
                var curTime = new Date().getTime();
                ticks += curTime - prevTime;
                prevTime = curTime;

                res = cb(res.vars, ticks);

                execute(res.ops);

                if(res.playing) requestAnimationFrame(anim);
            }

            anim();
        }

        return {
            evaluate: function(init, cb) {
                execute(init.ops);

                animate(init, cb);
            }
        };
    }

    function render(dims, particles, coords, alpha) {
        var xDims = dims.x;
        var yDims = dims.y;
        var zDims = dims.z;

        for(var i = 0, len = coords.length; i < len; i++) {
            var coord = coords[i];

            particles.alpha.value[coord.x + coord.y * xDims * yDims + coord.z * zDims ] = alpha;
        }

        particles.alpha.needsUpdate = true;
    }

    function initParticles(scene, dims) {
        var x = dims.x;
        var y = dims.y;
        var z = dims.z;
        var dim = 200; // XXX
        var dimHalf = dim / 2;
        var attributes = {
            alpha: {
                type: 'f',
                value: []
            }
        };

        var material = new THREE.ShaderMaterial({
            uniforms: {
                color: {
                    type: 'c',
                    value: new THREE.Color(0x0000ff)
                }
            },
            attributes: attributes,
            vertexShader: $('#vertexshader').text(),
            fragmentShader: $('#fragmentshader').text(),
            transparent: true
        });
        var geometry = new THREE.Geometry();

        for(var xi = 0, xlen = x; xi < xlen; xi++) {
            for(var yi = 0, ylen = y; yi < ylen; yi++) {
                for(var zi = 0, zlen = z; zi < zlen; zi++) {
                    geometry.vertices.push(new THREE.Vector3(
                        xi * dim / (x - 1) - dimHalf,
                        yi * dim / (y - 1) - dimHalf,
                        zi * dim / (z - 1) - dimHalf
                    ));
                }
            }
        }

        var particles = new THREE.ParticleSystem(
            geometry,
            material
        );

        scene.add(particles);

        return attributes;
    }

    return initPreview;
});

@@ -853,482 +853,8 @@
 );%0A%0A
-        function execute(fn) %7B%0A            fn.forEach(function(op) %7B%0A                if(!op) return;%0A%0A                var o = %7B%0A                    on: function() %7B%0A                        render(dims, particles, op.coords, 1);%0A                    %7D,%0A                    off: function() %7B%0A                        render(dims, particles, op.coords, 0);%0A                    %7D%0A                %7D%5Bop.op%5D();%0A            %7D);%0A%0A            renderer.render(scene, camera);%0A        %7D%0A%0A
     
@@ -863,32 +863,32 @@
   var prevTime;%0A
+
         var tick
@@ -1367,32 +1367,506 @@
 m();%0A        %7D%0A%0A
+        function execute(fn) %7B%0A            fn.forEach(function(op) %7B%0A                if(!op) return;%0A%0A                var o = %7B%0A                    on: function() %7B%0A                        render(dims, particles, op.coords, 1);%0A                    %7D,%0A                    off: function() %7B%0A                        render(dims, particles, op.coords, 0);%0A                    %7D%0A                %7D%5Bop.op%5D();%0A            %7D);%0A%0A            renderer.render(scene, camera);%0A        %7D%0A%0A
         return %7B
@@ -2247,16 +2247,16 @@
 ds%5Bi%5D;%0A%0A
+
         
@@ -2332,17 +2332,16 @@
  * zDims
- 
 %5D = alph

Tidy up