The sketch here is inspired by
this page which references “
Wilson, J., Robinson, J., & Piggins, D. (1983) Wobble cones and wobble holes: the stereokinetic effect revisited. Perception, 12, 187-193.“. You can
change the speed by moving your mouse:
[raw]
[/raw]
The author notes:
In stereokinetic depth, rotary movement enhances the impression of depth seen in patterns of concentric rings. Typically, rotation creates a vivid impression of a wobbly protruding cone or receding tunnel, or both, as in this demonstration. The effect indicates that the visual system has an in-built assumption that shapes tend to be rigid, and interprets the changing rings as a rigid 3-D shape moving in depth, rather than as an ameoba-like form changing shape.
Stereokinetic depth was actually first described by Musatti (1924; see Zanforlin, 1988). It was also used in the 1920's by the artist Marcel Duchamp, who called his spinning wobbly discs 'rotoreliefs'.
See:
- Clara, E., Regolin, L., Zanforlin, M., & Vallortigara, G. (2006). Domestic chicks perceive stereokinetic illusions. Perception, 35, 983-992.
- Shearer, R.R., & Gould, S.J. (1999) Of two minds and one nature. Science, 286, 1093-1094.
Wilson, J., Robinson, J., & Piggins, D. (1983) Wobble cones and wobble holes: the stereokinetic effect revisited. Perception, 12, 187-193.
- Zanforlin, M. (1988) The height of a stereokinetic cone: A quantitative determination of a 3-D effect from 2-D moving patterns without a "rigidity assumption". Psychological Research, 50, 162-172.
Code for the effect follows:
float cx,cy,diam;
float rotationsPerSecond = 0.5;
float angle = 0;
void setup() {
size(700,600);
cx = (width-100)/2 + 100;
cy = height / 2;
diam = height;
}
void draw() {
noStroke();
int back = 0;
background(255);
pushMatrix();
translate(cx,cy);
angle += 1 / 60.0 / 1 * 2 * PI * rotationsPerSecond;
rotate(angle);
ellipseMode(CENTER);
ellipse(0,0,diam,diam);
int outers = 7;
float diamshrink = 50;
for(int i = 0; i < outers; i++) {
float offset = i * diamshrink;
fill(back);
back = 255 - back;
ellipse(offset/2,0,diam - offset, diam - offset);
}
float cx2 = (outers-1) * diamshrink / 2, cy2 = 0, diam2 = diam - (outers-1)*diamshrink;
ellipse(cx2,cy2,5,5);
pushMatrix();
translate(cx2,cy2);
rotate(PI);
int inners = 6;
for(int i = 1; i < inners; i++) {
float offset = i * diamshrink;
fill(back);
back = 255 - back;
ellipse(offset/2,0,diam2 - offset, diam2 - offset);
}
popMatrix();
popMatrix();
drawSlider();
}
void drawSlider() {
rectMode(CENTER);
float cx = 100 / 2, cy = height / 2, ch = height - 100, cw = 80;
stroke(0);
fill(0);
rect(cx,cy,5,ch);
float sliderY = constrain(mouseY,cy-ch/2,cy+ch/2);
rect(cx,sliderY,cw,5);
rotationsPerSecond = map(sliderY,cy+ch/2,cy-ch/2,-2,2);
textAlign(CENTER,CENTER);
textSize(20);
text(""+round(rotationsPerSecond*10)/10.0,cx,cy-ch/2-30);
}