/**
*
spxlSpikyBall
*
*
* Version 1.0, 2009-02-24
*
* A sphere and some points... demonstration of the
* SuperPoint
* Processing Library.
*
* Controls
*
* - Mouse click/drag - move the ball
* - [space] - pause/unpause
* - [c]centre on/of
* - [w]ander on/off
* - [left] [right] [up] [down] - move to window border
* - [j]ump to random location
* - [m]ove to random location
* - [s]pin random speed
* - [page up] [page down] speed up/slow down
* - [x] stop spinning
*
*/
import processing.opengl.*;
import com.hardcorepawn.*;
// Magic fast points object :o)
SuperPoint p;
float SPHERE_RADIUS = 200;
float WIDTH_2; // Window width / 2 .. set in setup()
float HEIGHT_2; // Window height / 2 .. set in setup()
// User parameters
boolean paused = false;
boolean autoCentre = false;
boolean wander = true;
// State
float spinSpeed = 1.0;
float tSpinSpeed = 1.0; // target spinSpeed
float spinIncrement = 0.1;
// Origin
float ox = 0.0;
float oy = 0.0;
float oz = 0.0;
// Target origin
float tox = 0.0;
float toy = 0.0;
float toz = 0.0;
// Orientation
float theta = 0.0;
float phi = 0.0;
// These values determine the spin on separate axes
float thetaRatio = 0.003;
float phiRatio = 0.009;
// Easing
float easeValue = 0.1;
void setup()
{
if (online)
{
size(640, 480, OPENGL); // Applet-friendly size
cursor(CROSS);
}
else
{
size(screen.width, screen.height, OPENGL); // Fullscreen? :o)
noCursor();
}
background(0);
WIDTH_2 = width >> 1;
HEIGHT_2 = height >> 1;
p=new SuperPoint(this);
for(int i=0; i < 2000; i++)
{
addRandomPoint();
}
// Initial Location
ox = tox = 0;
oy = toy = 0;
oz = -10000; // Far away... Result is a nice zoom in effect. :o)
}
void draw()
{
hint(DISABLE_OPENGL_ERROR_REPORT); // Speed up rendering?
background(0);
// Move back to centre?
if (autoCentre && !mousePressed)
{
tox *= (1-easeValue);
toy *= (1-easeValue);
}
else if (wander) // Wander around
{
float n = 8*TWO_PI * noise(frameCount * 0.001);
float dx = cos(n);
float dy = sin(n);
tox = constrain(tox + dx, -WIDTH_2, WIDTH_2);
toy = constrain(toy + dy, -HEIGHT_2, HEIGHT_2);
}
// Move back and forth
toz = -100 + 100 * sin(frameCount * 0.01);
// Ease to target
ox = lerp(ox, tox, easeValue);
oy = lerp(oy, toy, easeValue);
oz = lerp(oz, toz, easeValue);
// Ease to target spin speed
spinSpeed = lerp(spinSpeed, tSpinSpeed, easeValue);
// Adjust orientation using spin speed
theta += spinSpeed * thetaRatio;
phi += spinSpeed * phiRatio;
// Translate origin
translate(WIDTH_2 + ox, HEIGHT_2 + oy, oz);
// Orient
rotateZ(theta);
rotateY(phi);
// Inner sphere
noStroke();
fill(0);
sphereDetail(30);
sphere(SPHERE_RADIUS);
// Draw the points (base of tips)
p.draw(12);
// Additional sets of points to make pointy tips
for (int i = 0; i < 8; i++)
{
scale(1.006 + 0.002 / (abs(spinSpeed)+1));
rotateZ(-thetaRatio * spinSpeed * 0.7);
rotateY(-phiRatio * spinSpeed * 0.7);
p.draw(11-i);
}
}
// Create a new random (evenly distributed) point on a random-radius sphere
void addRandomPoint()
{
float R = SPHERE_RADIUS * random(1, 1.5); // Random radius at least size of sphere redius
float z = random(-R, R); // Pick any z within bounds of sphere
float r = sqrt((R * R) - (z * z)); // Find radius of circle formed by intersection of sphere with plane Z = z
float t = random(TWO_PI); // Pick random angle around circumferemce of circle
float x = r * cos(t); // Locate point for the selected angle: x coordinate
float y = r * sin(t); // " " " " " " : y coordinate
p.addPoint(x, y, z, random(abs(z)/R),random(abs(x)/R),random(abs(y)/R),random(0.85));
}
void keyPressed()
{
// These key codes are for my keyboard... maybe different on yours
final int PAGE_UP = 33;
final int PAGE_DOWN = 34;
if (key == CODED)
switch (keyCode)
{
// Move to edge of window
case LEFT: tox = -HEIGHT_2; break;
case RIGHT: tox = WIDTH_2; break;
case UP: toy = -HEIGHT_2; break;
case DOWN: toy = HEIGHT_2; break;
// Spin speed adjustment
case PAGE_DOWN: tSpinSpeed -= spinIncrement; break;
case PAGE_UP: tSpinSpeed += spinIncrement; break;
default: // In case you need to work out what key you're pressing!
println(keyCode);
break;
}
else switch (key)
{
case ' ':
// Pause/unpause
paused = !paused;
if (paused)
noLoop();
else
loop();
break;
case 'c':
case 'C':
// Centre on/off
autoCentre = !autoCentre;
break;
case 'j':
case 'J':
// Jump to random position
ox = tox = random( -WIDTH_2, WIDTH_2);
oy = toy = random(-HEIGHT_2, HEIGHT_2);
break;
case 'm':
case 'M':
// Move to random position
tox = random( -WIDTH_2, WIDTH_2);
toy = random(-HEIGHT_2, HEIGHT_2);
break;
case 's':
case 'S':
{
// Random spin speed
// Random integer -2, -1, 0, 1 (2 isn't included as we account for equal value next)
float rnd = int(random(-3, 2));
// If less than exising value, use it, otherwise use one number higher
// so we don't get the same value as last time
tSpinSpeed = (rnd < tSpinSpeed) ? rnd : rnd + 1;
break;
}
case 'x':
case 'X':
// Stop spinning
tSpinSpeed = 0;
break;
case 'w':
case 'W':
// Wander on/off
wander = !wander;
break;
default:
// In case you need to work out what key you're pressing!
println(key);
break;
}
}
void mousePressed()
{
targetMouse();
}
void mouseDragged()
{
targetMouse();
}
// Set target location based on mouse position
void targetMouse()
{
tox = mouseX - WIDTH_2;
toy = mouseY - HEIGHT_2;
}