DPR

Creative Technologist

++

Teach our kids to code scriptographer scripts

Last year Christina Winkless and I created a poster for Emma Mulqueeny’s petition on teaching coding in schools.

Back then, we ended up releasing only 1 of our 7 poster designs. Below i’d like to share the other Scriptographer sketches I came up with for the other posters.

threeCircles.js

var blueCircle = new Path.Circle(new Point(-100, 110), 120);
blueCircle.fillColor = "#66CCCC";
blueCircle.blendMode = "multiply";

var greenCircle = new Path.Circle(new Point(100, 110), 120);
greenCircle.fillColor = "#CCCC66";
greenCircle.blendMode = "multiply";

var pinkCircle = new Path.Circle(new Point(0, 0), 120);
pinkCircle.fillColor = "#FF6666";
pinkCircle.blendMode = "multiply";

circleLines.js

var numberOfLines = 360;
var angle = 0, radius = 180;
var colors = ["#576372", "#5CC4BE", "#C8DC67", "#F26B6C", "#F6D86B", "#F26B43"];

for(var i = 0; i < numberOfLines; i++){

    angle = (i * (360 / numberOfLines)) * Math.PI / 180;

    var center = document.bounds.center;

    var p1 = center;
    var p2 = new Point(center.x + Math.cos(angle) * radius, center.y + Math.sin(angle) * radius);

    createLine(p1, p2);
}

function createLine(p1, p2){

    var line = new Path.Line(p1, p2){
        strokeColor:getRandomColor()
    };
}

function getRandomColor(){
	return colors[Math.floor(randomNumber(0, colors.length-1))];
}

function randomNumber(min, max){
    return min + Math.random() * (max - min);
}

petals.js

var numberOfLines = 360;
var angle = 0, radius = 190, lineRadius = 0, lineAngleIncrement = 0;
var colors = ["#576372", "#5CC4BE", "#C8DC67", "#F26B6C", "#F6D86B", "#F26B43"];

for(var i = 0; i < numberOfLines; i++){

    angle = (i * (360 / numberOfLines)) * Math.PI / 180;

    lineAngleIncrement += 0.07;

    lineRadius = Math.sin(lineAngleIncrement) * radius;

    var center = document.bounds.center;

    var p1 = center;
    var p2 = new Point(center.x + Math.cos(angle) * lineRadius, center.y + Math.sin(angle) * lineRadius);

    createLine(p1, p2);
}

function createLine(p1, p2){

    var line = new Path.Line(p1, p2){
        strokeColor:getRandomColor()
    };
}

function getRandomColor(){
	return colors[Math.floor(randomNumber(0, colors.length-1))];
}

function randomNumber(min, max){
    return min + Math.random() * (max - min);
}

nodes.js

var region = new Rectangle(0, 0, 400, 400);
var numberOfNodes = 100;
var nodesArray = [];
var nodeDistanceThreshold = 60;
var colors = ["#576372", "#5CC4BE", "#C8DC67", "#F26B6C", "#F6D86B", "#F26B43"];

for(var i = 0; i < numberOfNodes; i++){

    var x = randomNumber(0, region.width);
    var y = randomNumber(0, region.height);
    var radius = randomNumber(1, 30);

    createNode(x, y, radius);
}

for(var j = 0; j < nodesArray.length; j++){

    for(var k = 0; k < nodesArray.length; k++){

        var vector = nodesArray[j].position - nodesArray[k].position;

        if(Math.floor(vector.length) < nodeDistanceThreshold){

            var connectedLine = new Path.Line(nodesArray[j].position, nodesArray[k].position){
                strokeColor:getRandomColor(),
                opacity:0.2
            };
        }
    }
}

function createNode(x, y, radius){

    var node = new Path.Circle(new Point(x ,y), radius) {
        fillColor:getRandomColor(),
        blendMode:"multiply",
        opacity:1
    };

    nodesArray.push(node);
}

function getRandomColor(){
	return colors[Math.floor(randomNumber(0, colors.length-1))];
}

function randomNumber(min, max){
    return min + Math.random() * (max - min);
}

rectangles.js

var rows = 45
var columns = 36;
var colors = ["#576372", "#5CC4BE", "#C8DC67", "#F26B6C", "#F6D86B", "#F26B43"];

for(var x = 0; x < rows; x++){
    for(var y = 0; y < columns; y++){

        var size = randomNumber(5, 10);
        createRectangle(x * 10, y * 10, size, size);
    }
}

function createRectangle(x, y, width, height){

    var rectangle = new Rectangle(x - width/2, y - height/2, width, height);
    var roundedRectangle = new Path.RoundRectangle(rectangle, new Size(2, 2)){
        strokeColor:null,
        fillColor:getRandomColor()
    };
}

function getRandomColor(){
    return colors[Math.floor(randomNumber(0, colors.length-1))];
}

function randomNumber(min, max){
    return min + Math.random() * (max - min);
}

randomLines.js

var region = new Rectangle(0, 0, 400, 400);
var colors = ["#576372", "#5CC4BE", "#C8DC67", "#F26B6C", "#F6D86B", "#F26B43"];
var numberOfLines = 500;

for(var i = 0; i < numberOfLines; i++){

    var lineStart = new Point(randomNumber(0, region.width), randomNumber(0, region.height));
    var lineEnd = new Point(randomNumber(0, region.width), randomNumber(0, region.height));
    var path = new Path.Line(lineStart, lineEnd);

    path.style.strokeColor = getRandomColor();
    path.opacity = randomNumber(0.5, 1);
}

function getRandomColor(){
	return colors[Math.floor(randomNumber(0, colors.length-1))];
}

function randomNumber(min, max){
    return min + Math.random() * (max - min);
}

spiral.js

var circleRadius = 0, spiralRadius = 0, angle = 0;
var numberOfCircles = 100;

for(var i = 0; i < numberOfCircles; i++){

    angle++;
    spiralRadius += 2;
    circleRadius += 0.2;

    var x = (document.size.width / 2) + Math.cos(angle) * spiralRadius;
    var y = (document.size.height / 2) + Math.sin(angle) * spiralRadius;

    createCircle(x, y, circleRadius);
}

function createCircle(x, y, radius){

    var circle = new Path.Circle(new Point(x, y), radius){
        fillColor:"#5CC4BE"
    };
}

function randomNumber(min, max){
    return min + Math.random() * (max - min);
}
Posted in Work
Tagged ,

2 Comments

Generative 3D Structures Part I

The construction of everything in the universe relies on an underlying structure. Whether it’s the formation of bricks in a wall or the positions of the proton and neutron in the atom, everything is held together in a particular and pre-determined way.

When the theory of Generative systems is added to this equation, structures can be dynamically generated with an infinate number of results.

My recent experiments explore generative structure creation. These concepts originally started out as Scriptographer sketches which would then be rewrote as my first PyMEL scripts for Maya. The following scripts explore recursive branching, subdivision and a recreation of the popular fractal — The Sierpinski Tetrahedron.

The source code for the structures below can be found on my Github repository PyMEL Scripts.

Spherical branching fractal

Linear Rectangular division

Multiple Rectangular division

Multiple and random Rectangular division

The Sierpinski Tetrahedron

The Sierpinski Tetrahedron

Posted in Work
Tagged , , , , ,

Leave a comment

Merry Christmas 2011

presets["Snowflake"] = {
    axiom:"X+X+X+X+X+X",
    generations:5,
    angle:60,
    startingAngle:-90,
    stepSize:5,
    position:{x:0, y:0},
    commandsMap:{"F":"drawForward", "+":"turnLeft", "-":"turnRight", "[":"pushState", "]":"popState"},
    rules:[{production:"X", sucessor:["[F[+X][-X]FX]"]}, {production:"F", sucessor:["FF"]}]
};

I didn’t really have an excuse not to make some sort of Christmas art this year. My most recent project – Lsystems.js is perfectly suited for making fractals such as snowflakes. The snowflake Lsystem you see above, was created by simply modifying an existing tree Lsystem.

Click here if you like it.

Posted in Work
Tagged , , ,

Leave a comment

Introducing Lsystems.js

If you’ve recently been on my Github repository you’ll notice a new addition to my projects. Lsystem.js is a Scriptographer script for Adobe Illustrator. It allows users to generate Lsystem fractals through a list of available presets.

The script currently features:

  • 24 Lsystem presets
  • GUI to style, select and modify presets

At the moment the generator only supports DOL-systems, Stochastic L-systems and Bracketed OL-systems. I plan on adding support for parametric and context-sensitive Lsystems in a future release. For a full list of features to be added read here.

This script originally evolved from a canvas implementation I wrote back in October. Unhappy with the quality and finish of Canvas’ drawing API I decided to write a Scriptographer version instead.

If you’ve unfamiliar with what Lsystems are have a read through The Algorithmic Beauty of Plants. ABOP is a highly detailed paper about the history, theory and principles of modelling Lsystems in 2D an 3D.

I’ve wrote an introduction to Lindenmayer systems here. It goes though the basic concepts of how Lsystems work. I also plan on writing a guide to using this script soon, which should be available shortly after the next release of Lsystems.js.

You can download the latest version of this script here.

Posted in Work
Tagged , , , ,

5 Comments

MEL experiment – A Sphere of spheres

This was the output from recent experiment with MEL. MEL is powerful scripting language for Maya which is syntactically similar to Tcl and Perl.

Ever since I started to learn how to model in Maya I’ve always been fascinated with the arrangement of vertices in polygon structures, especially the spheres. This experiment was a learning exercise into understanding how they are arranged in 3D space.

Feel free to copy and paste the script below to generate your own.

$numOfInnerSpheres = 20;
$numOfRings = 20;
$sphereX = 0;
$sphereY = 0;
$sphereZ = 0;

$sphereOuterRadius = 70;
$sphereRadius = 0;
$sphereTwist = 0;

$sphereSize = 1;

for($i = 0; $i < $numOfRings; $i++){

	$sphereRadius = sin(deg_to_rad($i * (180 / $numOfRings))) * $sphereOuterRadius;
    $sphereTwist = cos(deg_to_rad($i * (180 / $numOfRings))) * $sphereOuterRadius;

	for($j = 0; $j < $numOfInnerSpheres; $j++){

		$sphereX = cos(deg_to_rad($sphereTwist + ($j * (360 / $numOfInnerSpheres)))) * $sphereRadius;
		$sphereY = sin(deg_to_rad($sphereTwist + ($j * (360 / $numOfInnerSpheres)))) * $sphereRadius;
		$sphereZ = cos(deg_to_rad($i * (180 / $numOfRings))) * $sphereOuterRadius;

		polySphere -sx 12 -sy 12;
		move $sphereX $sphereY $sphereZ;
		scale $sphereSize $sphereSize $sphereSize;
	}
}
Posted in Work
Tagged , ,

2 Comments