Merge branch 'integration'
[SugarCubes.git] / DanHorwitz.pde
1 //----------------------------------------------------------------------------------------------------------------------------------
2 static MidiOutput midiout;
3 int nNumRows = 6, nNumCols = 8;
4 boolean btwn (int a,int b,int c) { return a >= b && a <= c; }
5
6 public class _P extends BasicParameter {
7 _P(String label, double value) { super(label,value); }
8 void updateValue (double value) { super.updateValue(value); }
9 float Val () { return getValuef(); }
10 }
11
12 public class Pick {
13 Pick (String label, int _Def, int _Max) { Picks=_Max; Default = _Def; tag=label; }
14 int Cur() { return (CurCol-StartCol)*nNumRows + CurRow; }
15 int Picks, Default, CurRow, CurCol, StartCol, EndCol;
16 String tag;
17 }
18 //----------------------------------------------------------------------------------------------------------------------------------
19 float xMax,yMax,zMax;
20 public class xyz { float x,y,z;
21 xyz() {x=y=z=0;}
22 xyz(Point p ) {x=p.fx ; y=p.fy; z=p.fz;}
23 xyz(float _x,float _y,float _z) {x=_x ; y=_y ; z=_z ;}
24 void set(float _x,float _y,float _z) {x=_x ; y=_y ; z=_z ;}
25 float distance(xyz b) {return dist(x,y,z,b.x,b.y,b.z); }
26 float dot (xyz b) {return x*b.x + y*b.y + z*b.z; }
27 xyz minus (xyz b) {return new xyz(x-b.x,y-b.y,z-b.z); }
28 xyz plus (xyz b) {return new xyz(x+b.x,y+b.y,z+b.z); }
29 xyz plus (float b) {return new xyz(x+b ,y+b ,z+b ); }
30 xyz over (xyz b) {return new xyz(x/b.x,y/b.y,z/b.z); }
31 xyz times (float b) {return new xyz(x*b ,y*b ,z*b ); }
32
33 xyz RotateX (xyz o, float a) { return new xyz ( x,
34 cos(a)*(y-o.y) - sin(a)*(z-o.z) + o.y,
35 sin(a)*(y-o.y) + cos(a)*(z-o.z) + o.z); }
36
37 xyz RotateY (xyz o, float a) { return new xyz ( cos(a)*(x-o.x) - sin(a)*(z-o.z) + o.x,
38 y,
39 sin(a)*(x-o.x) + cos(a)*(z-o.z) + o.z); }
40
41 xyz RotateZ (xyz o, float a) { return new xyz ( cos(a)*(x-o.x) - sin(a)*(y-o.y) + o.x,
42 sin(a)*(x-o.x) + cos(a)*(y-o.y) + o.y,
43 z ); }
44
45
46 xyz setRand () { return new xyz ( random(xMax), random(yMax), random(zMax)); }
47 xyz setNorm () { return new xyz ( x / xMax, y / yMax, z / zMax); }
48
49
50 float interp (float a, float b, float c) { return (1-a)*b + a*c; }
51 xyz interpolate(float i, xyz d) { return new xyz ( interp(i,x,d.x), interp(i,y,d.y), interp(i,z,d.z)); }
52 }
53 //----------------------------------------------------------------------------------------------------------------------------------
54 public class hsb { float h,s,b;
55 hsb(color c) { h=hue(c); s=saturation(c); b=brightness(c); }
56 color Out() { return color(h%360.,constrain(s,0,100),constrain(b,0,100)); }
57 }
58
59 public class DPat extends SCPattern
60 {
61 float zSpinHue;
62 xyz xyzMax, xyz0, xyzMid, xyzHalf;
63
64 ArrayList picks = new ArrayList();
65 int nMaxCol = 0;
66 boolean bIsActive = false;
67 float Dist (xyz a, xyz b) { return dist(a.x,a.y,a.z,b.x,b.y,b.z); }
68 float c1c (float a) { return 100*constrain(a,0,1); }
69 int mapRow (int a) { return a == 52 ? 5 : btwn(a,53,57) ? a-53 : a; }
70 int unmapRow (int a) { return a == 5 ? 52 : btwn(a,0 , 4) ? a+53 : a; }
71 void SetLight (int row, int col, int clr){ if (midiout != null) midiout.sendNoteOn(col, unmapRow(row), clr); }
72 void keypad (int row, int col) {}
73 void onInactive() { bIsActive=false; }
74 void onActive () { bIsActive=true;
75 zSpinHue = 0;
76 for (int i=0; i<nNumRows ; i++) for (int j=0; j<nNumCols; j++) SetLight(i, j, 0);
77 for (int i=0; i<picks.size(); i++) UpdateLights((Pick)picks.get(i));
78 }
79 void StartRun(int deltaMs) {}
80 color CalcPoint(Point p) { return color(0,0,0); }
81 float CalcCone (xyz v1, xyz v2, xyz c) {
82 return degrees( acos ( v1.minus(c).dot(v2.minus(c)) / (sqrt(v1.minus(c).dot(v1.minus(c))) * sqrt(v2.minus(c).dot(v2.minus(c))) ) ));
83 }
84
85
86 void run(int deltaMs) {
87 StartRun(deltaMs);
88 zSpinHue += s_SpinHue ()*deltaMs*.05;
89 for (Point p : model.points) {
90 hsb cOld = new hsb(colors[p.index]);
91 hsb cNew = new hsb (CalcPoint(p));
92 if (s_Trails ()>0) cNew.b = max(cNew.b,cOld.b - (1-s_Trails()) * deltaMs);
93 if (s_Dim ()>0) cNew.b *= 1-s_Dim ();
94 if (s_Saturate ()>0) cNew.s += s_Saturate()*100;
95 if (s_SpinHue ()>0) cNew.h += zSpinHue;
96 if (s_ModHue ()>0) cNew.h += s_ModHue()*360;
97 colors[p.index] = cNew.Out();
98 }
99 }
100
101 void controllerChangeReceived(rwmidi.Controller cc) {
102 if (cc.getCC() == 7 && btwn(cc.getChannel(),0,7)) Sliders[cc.getChannel()] = 1.*cc.getValue()/127.;
103 }
104
105 float Sliders[] = new float[] {0,0,0,0,0,0,0,0};
106 float s_Trails () { return Sliders[0]; }
107 float s_Dim () { return Sliders[1]; }
108 float s_Saturate () { return Sliders[2]; }
109 float s_SpinHue () { return Sliders[3]; }
110 float s_ModHue () { return Sliders[4]; }
111
112 DPat(GLucose glucose) {
113 super(glucose);
114 xMax = model.xMax; yMax = model.yMax; zMax = model.zMax;
115 xyzMax = new xyz(xMax,yMax,zMax);
116 xyzMid = new xyz(xMax/2, yMax/2, zMax/2);
117 xyzHalf = new xyz(.5,.5,.5);
118 xyz0 = new xyz(0,0,0);
119 for (MidiInputDevice input : RWMidi.getInputDevices ()) { if (input.toString().contains("APC")) input .createInput (this);}
120 for (MidiOutputDevice output : RWMidi.getOutputDevices()) {
121 if (midiout == null && output.toString().contains("APC")) midiout = output.createOutput();
122 }
123 }
124
125 void UpdateLights(Pick P) {
126 if (P==null) return;
127 for (int i=0; i<nNumRows; i++) for (int j=P.StartCol; j<=P.EndCol; j++) SetLight(i, j, 0);
128 SetLight(P.CurRow, P.CurCol, 3);
129 }
130
131 Pick GetPick(int row, int col) {
132 for (int i=0; i<picks.size(); i++) { Pick P = (Pick)picks.get(i);
133 if (!btwn(col,P.StartCol,P.EndCol) ) continue;
134 if (!btwn(row,0,nNumRows-1) ) continue;
135 if (!btwn((col-P.StartCol)*nNumRows + row,0,P.Picks-1) ) continue;
136 return P;
137 }
138 return null;
139 }
140
141 void noteOffReceived(Note note) { if (!bIsActive) return;
142 int row = mapRow(note.getPitch()), col = note.getChannel();
143 UpdateLights(GetPick(row,col));
144 }
145
146 void noteOnReceived (Note note) { if (!bIsActive) return;
147 int row = mapRow(note.getPitch()), col = note.getChannel();
148 Pick P = GetPick(row,col);
149 if (P != null) { P.CurRow=row; P.CurCol=col;} else keypad(row, col);
150 }
151
152 Pick addPick(String name, int def, int nmax) {
153 Pick P = new Pick(name, def, nmax);
154 P.StartCol = nMaxCol;
155 P.EndCol = P.StartCol + int((nmax-1) / nNumRows);
156 nMaxCol = P.EndCol + 1;
157 P.CurRow = def % nNumRows;
158 P.CurCol = P.StartCol + def/nNumRows;
159 picks.add(P);
160 return P;
161 }
162 }
163 //----------------------------------------------------------------------------------------------------------------------------------
164 public class Pong extends DPat {
165 SinLFO x,y,z,dx,dy,dz;
166 float cRad; _P pSize;
167 Pick pChoose;
168
169 Pong(GLucose glucose) {
170 super(glucose);
171 cRad = xMax/15;
172 addModulator(dx = new SinLFO(6000, 500, 30000 )).trigger();
173 addModulator(dy = new SinLFO(3000, 500, 22472 )).trigger();
174 addModulator(dz = new SinLFO(1000, 500, 18420 )).trigger();
175 addModulator(x = new SinLFO(cRad, xMax - cRad, 0)).trigger(); x.modulateDurationBy(dx);
176 addModulator(y = new SinLFO(cRad, yMax - cRad, 0)).trigger(); y.modulateDurationBy(dy);
177 addModulator(z = new SinLFO(cRad, zMax - cRad, 0)).trigger(); z.modulateDurationBy(dz);
178 addParameter(pSize = new _P("Size", 0.4 ));
179 pChoose = addPick("Anim", 0 , 3);
180 }
181
182 color Calc(xyz p, xyz v) {
183 switch(pChoose.Cur()) {
184 case 0: return color(0,0,c1c(1 - min(v.distance(p), v.distance(xyzMax.minus(p)))*.5/cRad)); // balls
185 case 1: return color(0,0,c1c(1 - v.distance(p)*.5/cRad)); // ball
186 case 2: return color(0,0,c1c(1 - CalcCone(p,v,new xyz(xMax/2,0,zMax/2)) * max(.02,.45-pSize.Val()))); // spot
187 }
188 return color(0,0,0);
189 }
190
191 void StartRun(int deltaMs) { cRad = xMax*pSize.Val()/6; }
192 color CalcPoint(Point p) { return Calc(new xyz(p), new xyz(x.getValuef(), y.getValuef(), z.getValuef())); }
193 }
194 //----------------------------------------------------------------------------------------------------------------------------------
195 public class NDat {
196 float xz, yz, zz, hue, sat, speed, angle, den, sharp;
197 float xoff,yoff,zoff;
198 NDat (float _hue, float _sat, float _xz, float _yz, float _zz, float _sharp, float _den, float _speed, float _angle) {
199 hue=_hue; sat=_sat; xz=_xz; yz=_yz; zz =_zz; sharp=_sharp; den=_den; speed=_speed; angle=_angle;
200 xoff = random(100e3); yoff = random(100e3); zoff = random(100e3);
201 }
202 }
203
204 public class Noise extends DPat
205 {
206 int CurAnim = -1, numAnims = 6;
207 float zTime = random(10000), zSpin=0;
208 float rtime = 0, ttime = 0, transAdd=0;
209 int XSym=1,YSym=2,XyzSym=3,RadSym=4;
210
211 ArrayList noises = new ArrayList();
212 _P pSpeed, pSharp, pDensity, pSpin;
213 Pick pChoose, pSymm;
214
215 Noise(GLucose glucose) {
216 super(glucose);
217 addParameter(pSpin = new _P("Spin", .5 )); addParameter(pSpeed = new _P("Fast" , .55));
218 addParameter(pSharp = new _P("Shrp", .5 )); addParameter(pDensity = new _P("Dens" , .5 ));
219 pSymm = addPick("Symm", 0, 5);
220 pChoose = addPick("Anim", 0, 6);
221 }
222
223 void StartRun(int deltaMs) {
224 zTime += deltaMs*(pSpeed.Val()-.5)*.002 ;
225 zSpin += deltaMs*(pSpin .Val()-.5)*.01 ;
226 rtime += deltaMs;
227 transAdd = 1*(1 - constrain(rtime - ttime,0,1000)/1000);
228
229 if (pChoose.Cur() != CurAnim) {
230 noises.clear(); CurAnim = pChoose.Cur(); ttime = rtime;
231 switch(CurAnim) {
232 // hue sat xz yz zz srhp den mph angle
233 case 0: noises.add(new NDat(0 ,0 ,75 ,75 ,150,1 ,45 ,3 ,0 )); break; // drip
234 case 1: noises.add(new NDat(0 ,0 ,100,100,200,0 ,45 ,3 ,180)); break; // clouds
235 case 2: noises.add(new NDat(0 ,0 ,2 ,400,2 ,.5 ,40 ,3 ,0 )); break; // rain
236 case 3: noises.add(new NDat(40 ,100,100,100,200,0 ,30 ,1 ,180));
237 noises.add(new NDat(0 ,100,100,100,200,0 ,30 ,5 ,180)); break; // fire 1
238 case 4: noises.add(new NDat(0 ,100,40 ,40 ,40 ,.5 ,35 ,2.5,180));
239 noises.add(new NDat(20 ,100,40 ,40 ,40 ,.5 ,35 ,4 ,0 ));
240 noises.add(new NDat(40 ,100,40 ,40 ,40 ,.5 ,35 ,2 ,90 ));
241 noises.add(new NDat(60 ,100,40 ,40 ,40 ,.5 ,35 ,3 ,-90)); break; // machine
242 case 5: noises.add(new NDat(0 ,100,400,100,2 ,.5 ,35 ,3 ,225));
243 noises.add(new NDat(20 ,100,400,100,2 ,.5 ,35 ,2.5,45 ));
244 noises.add(new NDat(40 ,400,100,100,2 ,.5 ,35 ,2 ,135));
245 noises.add(new NDat(60 ,400,100,100,2 ,.5 ,35 ,1.5,-45)); break; // spark
246 }
247 }
248 }
249
250 color CalcPoint(Point p) {
251 color c = color(0,0,0);
252 int symm = pSymm.Cur();
253 for (int i=0;i<noises.size(); i++) {
254 xyz v = new xyz(p).RotateZ(xyzMid,zSpin);
255
256 if ((symm == XSym || symm == XyzSym) && v.x > xMax/2) v.x = xMax-v.x;
257 if ((symm == YSym || symm == XyzSym) && v.y > yMax/2) v.y = yMax-v.y;
258 if (( symm == XyzSym) && v.z > zMax/2) v.z = zMax-v.z;
259
260 NDat n = (NDat) noises.get(i);
261 float deg = radians(n.angle + (symm==XyzSym?45:0));
262 float zx = zTime * n.speed * sin(deg),
263 zy = zTime * n.speed * cos(deg),
264 sharp = 1/constrain(2-n.sharp - 2*pSharp.Val(),0,1);
265
266 float b = (symm==RadSym ? noise(zTime*n.speed+n.xoff-Dist(v,xyzMid)/n.xz)
267 : noise(v.x/n.xz+zx+n.xoff,v.y/n.yz+zy+n.yoff,v.z/n.zz+n.zoff))
268 *1.8-.4 + n.den/100 + pDensity.Val() -1;
269
270 b += n.den/100 + pDensity.Val() -1;
271 b = b < .5 ? pow(b,sharp) : 1-pow(1-b,sharp);
272 b += transAdd;
273 c = blendColor(c,color(n.hue,n.sat,c1c(b)),ADD);
274 }
275 return c;
276 }
277 }
278 //----------------------------------------------------------------------------------------------------------------------------------
279 public class Play extends DPat
280 {
281 int nBeats = 0;
282 _P pAmp, pRotX, pRotY, pRotZ, pRad;
283 Pick pTimePattern, pTempoMult, pShape;
284
285 Play(GLucose glucose) {
286 super(glucose);
287 addParameter(pAmp = new _P("Amp" , .2 ));
288 addParameter(pRotX = new _P("RotX", 0 ));
289 addParameter(pRotY = new _P("RotY", 0 ));
290 addParameter(pRotZ = new _P("RotZ", 0 ));
291 addParameter(pRad = new _P("Rad" , .1 ));
292
293 pTimePattern = addPick("TPat", 0 , 5 );
294 pTempoMult = addPick("TMul", 5 , 6 );
295 pShape = addPick("Shap", 8 , 10 );
296
297 lx.tempo.setBpm(30);
298 }
299
300 float t,a;
301 xyz cPrev = new xyz(), cCur = new xyz(), cMid = new xyz(), cMidNorm;
302 float LastBeat=3, LastMeasure=3;
303 int CurRandTempo = 1;
304
305 void StartRun(int deltaMs) {
306 t = lx.tempo.rampf();
307 a = pAmp.Val();
308
309 if (t<LastMeasure) { CurRandTempo = int(random(4)); } LastMeasure = t;
310
311 switch (pTempoMult.Cur()) {
312 case 0: t = t; break;
313 case 1: t = (t*2. )%1.; break;
314 case 2: t = (t*4. )%1.; break;
315 case 3: t = (t*8. )%1.; break;
316 case 4: t = (t*16.)%1.; break;
317 case 5: t = (t*pow(2,CurRandTempo))%1.; break;
318 }
319
320 if (t<LastBeat) { cPrev = cCur; cCur = cCur.setRand(); } LastBeat = t;
321
322 switch (pTimePattern.Cur()) {
323 case 0: t = sin(PI*t); break;
324 case 1: t = norm(sin(2*PI*(t+PI/2)),-1,1); break;
325 case 2: t = t; break;
326 case 3: t = constrain(int(t*8)/7.,0,1); break;
327 case 4: t = t*t*t; break;
328 }
329
330 cMid = cPrev.interpolate(t,cCur);
331 cMidNorm = cMid.setNorm();
332 }
333
334 color CalcPoint(Point p) {
335 xyz V = new xyz(0,0,0);
336 xyz P = new xyz(p).setNorm(). RotateX(xyzHalf,pRotX.Val()*PI*2).
337 RotateY(xyzHalf,pRotY.Val()*PI*2).
338 RotateZ(xyzHalf,pRotZ.Val()*PI*2);
339 xyz Px = new xyz(p);
340
341 float mp = min(P.x, P.z);
342 float yt = map(t,0,1,.5-a/2,.5+a/2);
343 switch (pShape.Cur()) {
344
345 case 0: V = new xyz(P.x, yt , P.z); break; // bouncing line
346 case 1: V = new xyz(P.x, map(cos(PI*t * P.x),-1,1,0,1) , P.z); break; // top tap
347 case 2: V = new xyz(P.x, a*map(P.x<.5?P.x:1-P.x,0,.5 ,0,t-.5)+.5, P.z); break; // V shape
348 case 3: V = new xyz(P.x, P.x < cMidNorm.x ? map(P.x,0,cMidNorm.x, .5,yt) :
349 map(P.x,cMidNorm.x,1, yt,.5), P.z); break; // Random V shape
350
351 case 4: V = new xyz(P.x, .5*(P.x < cMidNorm.x ? map(P.x,0,cMidNorm.x, .5,yt) :
352 map(P.x,cMidNorm.x,1, yt,.5)) +
353 .5*(P.z < cMidNorm.z ? map(P.z,0,cMidNorm.z, .5,yt) :
354 map(P.z,cMidNorm.z,1, yt,.5)), P.z); break; // Random Pyramid shape
355
356 case 5: V = new xyz(P.x, a*map((P.x-.5)*(P.x-.5),0,.25,0,t-.5)+.5, P.z); break; // wings
357 case 6: V = new xyz(P.x, a*map((mp -.5)*(mp -.5),0,.25,0,t-.5)+.5, P.z); break; // wings
358
359
360 case 7: V = new xyz(cMid.x,cMid.y,cMid.z);
361 return color(0,0,c1c(1 - (V.distance(Px) > (pRad.getValuef()+.1)*100?1:0)) ); // sphere
362
363 case 8: V = new xyz(cMid.x,cMid.y,cMid.z);
364 return color(0,0,c1c(1 - CalcCone(Px,V,xyzMid) * 0.02 > .5?1:0)); // cone
365
366 }
367
368 return color(0,0,c1c(1 - V.distance(P)/pRad.getValuef() > .5?1:0));
369 }
370 }
371 //----------------------------------------------------------------------------------------------------------------------------------