-
Notifications
You must be signed in to change notification settings - Fork 0
/
Sphere.pde
150 lines (140 loc) · 3.26 KB
/
Sphere.pde
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/**
* Sphere
*/
float angle = 0.0;
float rSize; // rectangle size
float sRadius; // sphere radius
Vector vnew, axis, mouse;
Quaternion vq, rotq, rotqc, rotqf;
Vector[] points, pointsNew;
int N = 40;
int transitionPos = 0;
int transitionMax = 200;
void setup() {
size(640, 360, P3D);
sRadius = min(width, height) / 4;
rSize = width / 48;
noStroke();
fill(204, 204);
// Quaternion & vectors needed for rotation
axis = new Vector();
mouse = new Vector ();
vq = new Quaternion ();
rotq = new Quaternion();
rotqc = new Quaternion();
rotqf = new Quaternion();
vnew = new Vector();
// Points randomly places then evenly distributed
points = new Vector[N];
pointsNew = new Vector[N];
for(int i=0; i<N; i++) {
points[i] = new Vector();
points[i].normalizedRandom();
pointsNew[i] = new Vector();
}
updatePoints();
}
void draw() {
background(0);
translate(width/2, height/2);
renderAxis();
renderTiles();
}
void computeRotation() {
// Compute quaternion
rotq.set (-angle, axis);
rotqc.conj(rotq);
}
void renderTiles() {
Vector p;
stroke(color(255, 255, 255));
color from = color(255, 128, 0);
color to = color(0, 128, 255);
for (int i=0; i<N; i++) {
p = points[i];
// Apply rotation to the point if any
if (angle != 0) {
vq.set(p);
rotqf.mult(rotq, vq);
p.mult(rotqf, rotqc);
}
if (transitionPos < transitionMax) {
Vector pn = pointsNew[i];
// We need to also rotate the new points on transition :(
if (angle != 0) {
vq.set(pn);
rotqf.mult(rotq, vq);
pn.mult(rotqf, rotqc);
}
// Interpolate the current point up to its new position
p.lerpVector(pn, transitionPos / (float)transitionMax);
}
// Draw the rectangle at the end of the rotated vector
fill(lerpColor(from, to, i/(float)N));
pushMatrix();
translate (p.x*sRadius, p.y*sRadius, p.z*sRadius);
rect(-rSize, -rSize, rSize*2, rSize*2);
popMatrix();
}
// Advance transition
if (transitionPos < transitionMax) {
transitionPos++;
} else if (transitionPos == transitionMax) {
// On end of transition, swap the position buffers
Vector[] tmp = points;
points = pointsNew;
pointsNew = tmp;
transitionPos++;
}
}
void renderAxis() {
// Draw the mouse vector
stroke(color(0, 0, 255));
line (0, 0, 0, mouse.x, mouse.y, mouse.z);
// Draw the axis vector
stroke(color(255, 0, 0));
line (0, 0, 0, axis.x*sRadius, axis.y*sRadius, axis.z*sRadius);
}
void mouseClicked() {
if (mouseButton == LEFT) {
if (N < points.length) {
N++;
updatePoints();
}
} else if (mouseButton == RIGHT) {
if (N > 0) {
N--;
updatePoints();
}
}
}
void mouseMoved() {
mouse.x = mouseX-width/2;
mouse.y = mouseY-height/2;
mouse.z =0;
float l = mouse.length() / (2*sRadius);
if (l > 0.5) {
l = 1 - l;
}
if (l > 0.1) {
l -= 0.1;
angle = l / 10.0;
axis.x = -mouse.y;
axis.y = mouse.x;
axis.z = mouse.z;
axis.normalize();
computeRotation();
} else {
angle = 0;
}
}
void updatePoints() {
// Copy current positions
for (int i=0; i<N; i++) {
pointsNew[i].set(points[i]);
}
// Compute new postions
distribute(N, pointsNew);
// Start transition
transitionPos = 0;
}