Tutorial on Processing: rotateX, rotateY, line, millis, mousePressed, map, arrays

This sketch displays a growing 3D spiral. If the viewer clicks the mouse on the display window, this causes rotations of the x and y axis so the spiral produced appears in a different position. The color of the spiral also changes. This means multiple spirals can be shown in the window. If no changes are made for a set period of time, everything is erased and the display starts over again. The xyz axes are shown in the upper left and these are erased when the mouse is clicked.

Here is another screen shot, after some mouse clicks:

Notice the xyz axes. They are not displayed perfectly and help would be appreciated on this matter!

Using mousePressed and map to get values

My code for producing different spirals does this by rotating around the x and rotating around the y axis based on a calculating using the mouse position when the button is pressed. The mousePressed function is defined by Processing to be invoked when the mouse button is pressed. The programmer (you and I) write the code. The first line of my function is a call to my function eraseaxes. This erases the xyz axes in the current position. The next two lines do the calculation of values for the rotation of axes. The calculation is arbitrary. Processing has a function called map. Consider the line:

rotY =map(mouseX, 0, width, -PI, PI);

The map function in this case returns: -PI + (mouseX/width)*2*PI.

Putting it another way, this function makes the interval from 0 to width correspond to the interval from –PI to PI.

Next in the mousePressed function (and this could be done earlier or later in the function), my code updates last:

last = millis();

The last task is to set up for a new color to be used to draw the spiral. The color is specified using 3 arrays: colsr, colsg, colsb. The variable col is used to index these arrays.

col++;

if (col==colsr.length) col=0;

Using millis for detecting a pause

I want the sketch to erase everything and start with the original rotation if nothing happens for a certain period of time. Detecting something NOT happening requires a computation. Processing has a function called millis() that returns the number of milliseconds since the application started. I declare a variable last and another variable rest, that is, essentially, a constant. The variable last is set in the setup function and also in each mousePressed function. Then in the draw function, I put the code

if ((millis()-last)>rest) {

rotY = 0;

rotX = 0;

background(255);

}

The condition is: if the current time minus last is more than rest, then it is time to do the resetting.

Drawing a spiral using line for line segments

The spiral is approximated using line segments. Visualize the coils of the spiral to be segmented circles in the xy plane with z values increasing. I created a function to make a spiral with parameters the x y x of the center for the bottom circle, a value dr that specifies the angle for the line segment, a value dh that specifies the increment in the z direction, and the number of turns (cycles).

The draw function calls the spiral function to draw 1, 2, and then 10 turns and then re-starts. Note that this means portions of the spiral are re-drawn: first a spiral with one turn, then a spiral with 2 turns, and so on.

Drawing and erasing the xyz axes

I decided I wanted to see the xyz axes on the display screen, and in 3 different colors. This is accomplished by setting and resetting the stroke color and then using line:

void drawaxes() {

stroke(0);

line(0,0,0,50,0,0);

stroke(200,200,100);

line(0,0,0,0,50,0);

stroke(40,150,20);

line(0,0,0,0,0,50);

}

I would have liked making these lines bigger, but the strokeweight function is not available in P3D.

The function to erase these axes is easy enough: just use a stroke color of 255. See all the code below. The delicate issue is when to invoke this function. After some experimentation, I put the call in the mousePressed function. There still can be problems.

Implementation of spiral

The code for the spiral sketch is the following:

int cycles = 1;

float rotX, rotY;

float last;

float rest;

int[] colsr = {200, 255,255, 255, 0, 0, 0};

int[] colsg = {100, 0, 255, 0, 255,255,0};

int[] colsb = {50, 0, 0, 255, 0, 255,255};

int col = 0;

void setup() {

size(800,600,P3D);

frameRate(6);

last = millis();

rest = 10000;

background(255);

}

void draw() {

translate(width/4,height/4);

if ((millis()-last)>rest) {

rotY = 0;

rotX = 0;

background(255);

}

rotateY(rotY);

rotateX(rotX);

drawaxes();

stroke(colsr[col],colsg[col],colsb[col]);

spiral(100,100,0,50,PI/10,2,cycles);

cycles++;

if (cycles>10) {

cycles = 1;

}

}

void spiral(float x, float y, float z, float rad, float dr,float dh, float cycles) {

float xx,yy,zz,a;

float xxo,yyo,zzo;

xxo=x+rad*cos(0);

yyo=y+rad*sin(0);

zzo=z-dh;

zz = z-dh;

for (int c=0;c<cycles;c++) {

for (a=0;a<2*PI;a+=dr) {

xx = x+rad*cos(a);

yy = y+rad*sin(a);

zz+=dh;

line(xx,yy,zz,xxo,yyo,zzo);

xxo=xx;

yyo=yy;

zzo=zz;

}

}

}

void mousePressed() {

eraseaxes();

rotY =map(mouseX, 0, width, -PI, PI);

rotX =map(mouseY, 0, height, -PI,PI);

last = millis();

col++;

if (col==colsr.length) col=0;

}

void eraseaxes() {

stroke(255);

line(0,0,0,50,0,0);

line(0,0,0,0,50,0);

line(0,0,0,0,0,50);

}

void drawaxes() {

stroke(0);

line(0,0,0,50,0,0);

stroke(200,200,100);

line(0,0,0,0,50,0);

stroke(40,150,20);

line(0,0,0,0,0,50);

}

Exercises:

  1. Make the spiral segments more obvious (bigger). Hint: change the values in the function call that correspond to dr and dh.
  2. Make the spiral have fewer or greater number of turns.
  3. Add colors to the list of colors specified in the 3 arrays.
  4. Modify the sketch to draw more than one spiral.