//----------------------------------------------------------------------------------------------------------------------------------
-static MidiOutput midiout;
-int nNumRows = 5, nNumCols = 8;
-float xdMax,ydMax,zdMax;
-String DanTextLine1 = "", DanTextLine2 = "";
+int NumApcRows=4, NumApcCols=8;
-boolean btwn (int a,int b,int c) { return a >= b && a <= c; }
-boolean btwn (double a,double b,double c) { return a >= b && a <= c; }
+boolean btwn (int a,int b,int c) { return a >= b && a <= c; }
+boolean btwn (double a,double b,double c) { return a >= b && a <= c; }
+float interp (float a, float b, float c) { return (1-a)*b + a*c; }
+float randctr (float a) { return random(a) - a*.5; }
+float min (float a, float b, float c, float d) { return min(min(a,b),min(c,d)); }
+float pointDist(LXPoint p1, LXPoint p2) { return dist(p1.x,p1.y,p1.z,p2.x,p2.y,p2.z); }
+float xyDist (LXPoint p1, LXPoint p2) { return dist(p1.x,p1.y,p2.x,p2.y); }
+float distToSeg(float x, float y, float x1, float y1, float x2, float y2) {
+ float A = x - x1, B = y - y1, C = x2 - x1, D = y2 - y1;
+ float dot = A * C + B * D, len_sq = C * C + D * D;
+ float xx, yy,param = dot / len_sq;
+
+ if (param < 0 || (x1 == x2 && y1 == y2)) { xx = x1; yy = y1; }
+ else if (param > 1) { xx = x2; yy = y2; }
+ else { xx = x1 + param * C;
+ yy = y1 + param * D; }
+ float dx = x - xx, dy = y - yy;
+ return sqrt(dx * dx + dy * dy);
+}
public class Pick {
- Pick (String label, int _Def, int _Max) { NumPicks=_Max; Default = _Def; tag=label; }
- int Cur() { return (CurRow-StartRow)*nNumCols + CurCol; }
- int NumPicks, Default, CurRow, CurCol, StartRow, EndRow;
- String tag;
-}
-//----------------------------------------------------------------------------------------------------------------------------------
-public class _DhP extends BasicParameter {
- double dflt;
- _DhP (String label, double value) { super(label,value); dflt=value; }
- void Set (double value) { super.updateValue(value); }
- void reset () { super.updateValue(dflt); }
- float Val () { return getValuef(); }
- boolean ZeroOrOne () { return Val()==0 || Val() == 1; }
-}
+ int NumPicks, Default ,
+ CurRow , CurCol ,
+ StartRow, EndRow ;
+ String tag , Desc[] ;
+
+ Pick (String label, int _Def, int _Num, int nStart, String d[]) {
+ NumPicks = _Num; Default = _Def;
+ StartRow = nStart; EndRow = StartRow + floor((NumPicks-1) / NumApcCols);
+ tag = label; Desc = d;
+ reset();
+ }
-public class IndexNums {
- int point ;//, cube , tower , face , strip ;
- int nPoints ;//, nCubes, nTowers, nFaces, nStrips ;
-// boolean isHoriz;
- void reset() { point=0;}//cube=tower=face=strip=0; }
+ int Cur() { return (CurRow-StartRow)*NumApcCols + CurCol; }
+ String CurDesc() { return Desc[Cur()]; }
+ void reset() { CurCol = Default % NumApcCols; CurRow = StartRow + Default / NumApcCols; }
+
+ boolean set(int r, int c) {
+ if (!btwn(r,StartRow,EndRow) || !btwn(c,0,NumApcCols-1) ||
+ !btwn((r-StartRow)*NumApcCols + c,0,NumPicks-1)) return false;
+ CurRow=r; CurCol=c; return true;
+ }
}
-IndexNums iCur = new IndexNums();
-//----------------------------------------------------------------------------------------------------------------------------------
-public class xyz { float x,y,z;
- xyz() {x=y=z=0;}
- xyz(Point p ) {x=p.fx ; y=p.fy; z=p.fz;}
- xyz(float _x,float _y,float _z) {x=_x ; y=_y ; z=_z ;}
- void set(float _x,float _y,float _z) {x=_x ; y=_y ; z=_z ;}
- float distance(xyz b) {return dist(x,y,z,b.x,b.y,b.z); }
- float dot (xyz b) {return x*b.x + y*b.y + z*b.z; }
- xyz minus (xyz b) {return new xyz(x-b.x,y-b.y,z-b.z); }
- xyz plus (xyz b) {return new xyz(x+b.x,y+b.y,z+b.z); }
- xyz plus (float b) {return new xyz(x+b ,y+b ,z+b ); }
- xyz over (xyz b) {return new xyz(x/b.x,y/b.y,z/b.z); }
- xyz times (float b) {return new xyz(x*b ,y*b ,z*b ); }
-
- xyz RotateX (xyz o, float a) { return new xyz ( x,
- cos(a)*(y-o.y) - sin(a)*(z-o.z) + o.y,
- sin(a)*(y-o.y) + cos(a)*(z-o.z) + o.z); }
-
- xyz RotateY (xyz o, float a) { return new xyz ( cos(a)*(x-o.x) - sin(a)*(z-o.z) + o.x,
- y,
- sin(a)*(x-o.x) + cos(a)*(z-o.z) + o.z); }
-
- xyz RotateZ (xyz o, float a) { return new xyz ( cos(a)*(x-o.x) - sin(a)*(y-o.y) + o.x,
- sin(a)*(x-o.x) + cos(a)*(y-o.y) + o.y,
- z ); }
-
- xyz setRand () { return new xyz ( random(xdMax), random(ydMax), random(zdMax)); }
- xyz setNorm () { return new xyz ( x / xdMax, y / ydMax, z / zdMax); }
-
- float interp (float a, float b, float c) { return (1-a)*b + a*c; }
- xyz interpolate(float i, xyz d) { return new xyz ( interp(i,x,d.x), interp(i,y,d.y), interp(i,z,d.z)); }
+
+public class DBool {
+ boolean def, b;
+ String tag;
+ int row, col;
+ void reset() { b = def; }
+ boolean set (int r, int c, boolean val) { if (r != row || c != col) return false; b = val; return true; }
+ DBool(String _tag, boolean _def, int _row, int _col) {
+ def = _def; b = _def; tag = _tag; row = _row; col = _col;
+ }
}
//----------------------------------------------------------------------------------------------------------------------------------
public class DPat extends SCPattern
{
- float zSpinHue;
- xyz xyzdMax, xyz0, xyzMid, xyzHalf;
- PFont itemFont = createFont("Lucida Grande", 11);
- ArrayList picklist = new ArrayList();
- ArrayList paramlist = new ArrayList();
- int nMaxRow = 0;
- boolean bIsActive = false;
- float NoiseMove = random(10000);
-
- float Dist (xyz a, xyz b) { return dist(a.x,a.y,a.z,b.x,b.y,b.z); }
- int c1c (float a) { return int(100*constrain(a,0,1)); }
- int mapRow (int a) { return btwn(a,53,57) ? a-53 : a; }
- int unmapRow (int a) { return btwn(a,0 , 4) ? a+53 : a; }
- void SetLight (int row, int col, int clr){ if (midiout != null) midiout.sendNoteOn(col, unmapRow(row), clr); }
- void keypad (int row, int col) { println(row + " " + col); }
- void onInactive() { bIsActive=false; DanTextLine1 = ""; DanTextLine2 = ""; uiDebugText.setText(""); }
- void onActive () { bIsActive=true;
- zSpinHue = 0;
- for (int i=0; i<paramlist.size(); i++) ((_DhP)paramlist.get(i)).reset();
- while (lx.tempo.bpm() > 40) lx.tempo.setBpm(lx.tempo.bpm()/2);
- UpdateLights();
- }
- void StartRun(int deltaMs) { }
- color CalcPoint(xyz p) { return color(0,0,0); }
- float CalcCone (xyz v1, xyz v2, xyz c) {
- 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))) ) ));
- }
+ ArrayList<Pick> picks = new ArrayList<Pick> ();
+ ArrayList<DBool> bools = new ArrayList<DBool> ();
- void AddDanText() {
- DanTextLine1 = "APC40: ";
- for (int i=0; i<picklist.size() ; i++) { Pick P = (Pick)picklist.get(i); DanTextLine1 += P.tag + ": " + P.Cur() + " "; }
- DanTextLine1 += " X-Symm: " + (_XSym ? "ON" : "OFF") + " ";
- DanTextLine1 += " Y-Symm: " + (_YSym ? "ON" : "OFF") + " ";
- DanTextLine1 += " Z-Symm: " + (_ZSym ? "ON" : "OFF") + " ";
- DanTextLine1 += " Rad-Sym: " + (_RadSym ? "ON" : "OFF") + " ";
-// DanTextLine1 += " Horiz: " + (_Horiz ? "ON" : "OFF") + " ";
-// DanTextLine1 += " Vert: " + (_Vert ? "ON" : "OFF") + " ";
+ PVector mMax, mCtr, mHalf;
- DanTextLine2 = "SLIDERS: ";
- for (int i=0; i<8; i++) if (SliderText[i] != "") { DanTextLine2 += SliderText[i] + ": " + Sliders[i] + " "; }
+ MidiOutput APCOut;
+ int nMaxRow = 53;
+ float LastJog = -1;
+ float[] xWaveNz, yWaveNz;
+ int nPoint , nPoints;
+ PVector xyzJog = new PVector(), modmin;
- uiDebugText.setText(DanTextLine1, DanTextLine2);
+ float NoiseMove = random(10000);
+ BasicParameter pSpark, pWave, pRotX, pRotY, pRotZ, pSpin, pTransX, pTransY;
+ DBool pXsym, pYsym, pRsym, pXdup, pXtrip, pJog, pGrey;
+
+ float lxh () { return lx.getBaseHuef(); }
+ int c1c (float a) { return round(100*constrain(a,0,1)); }
+ float interpWv(float i, float[] vals) { return interp(i-floor(i), vals[floor(i)], vals[ceil(i)]); }
+ void setNorm (PVector vec) { vec.set(vec.x/mMax.x, vec.y/mMax.y, vec.z/mMax.z); }
+ void setRand (PVector vec) { vec.set(random(mMax.x), random(mMax.y), random(mMax.z)); }
+ void setVec (PVector vec, LXPoint p) { vec.set(p.x, p.y, p.z); }
+ void interpolate(float i, PVector a, PVector b) { a.set(interp(i,a.x,b.x), interp(i,a.y,b.y), interp(i,a.z,b.z)); }
+ void StartRun(double deltaMs) { }
+ float val (BasicParameter p) { return p.getValuef(); }
+ color CalcPoint(PVector p) { return lx.hsb(0,0,0); }
+ color blend3(color c1, color c2, color c3) { return blendColor(c1,blendColor(c2,c3,ADD),ADD); }
+
+ void rotateZ (PVector p, PVector o, float nSin, float nCos) { p.set( nCos*(p.x-o.x) - nSin*(p.y-o.y) + o.x , nSin*(p.x-o.x) + nCos*(p.y-o.y) + o.y,p.z); }
+ void rotateX (PVector p, PVector o, float nSin, float nCos) { p.set(p.x,nCos*(p.y-o.y) - nSin*(p.z-o.z) + o.y , nSin*(p.y-o.y) + nCos*(p.z-o.z) + o.z ); }
+ void rotateY (PVector p, PVector o, float nSin, float nCos) { p.set( nSin*(p.z-o.z) + nCos*(p.x-o.x) + o.x,p.y, nCos*(p.z-o.z) - nSin*(p.x-o.x) + o.z ); }
+
+ BasicParameter addParam(String label, double value) { BasicParameter p = new BasicParameter(label, value); addParameter(p); return p; }
+
+ PVector vT1 = new PVector(), vT2 = new PVector();
+ float calcCone (PVector v1, PVector v2, PVector c) { vT1.set(v1); vT2.set(v2); vT1.sub(c); vT2.sub(c);
+ return degrees(PVector.angleBetween(vT1,vT2)); }
+
+ Pick addPick(String name, int def, int _max, String[] desc) {
+ Pick P = new Pick(name, def, _max+1, nMaxRow, desc);
+ nMaxRow = P.EndRow + 1;
+ picks.add(P);
+ return P;
}
- void run(int deltaMs) {
- NoiseMove += deltaMs;
- xdMax = model.xMax;
- ydMax = model.yMax;
- zdMax = model.zMax;
- xyzdMax = new xyz(xdMax,ydMax,zdMax);
- xyzMid = new xyz(xdMax/2, ydMax/2, zdMax/2);
- StartRun (deltaMs);
- zSpinHue += s_SpinHue ()*deltaMs*.05;
- float fSharp = 1/(1.01-pSharp.Val());
- AddDanText();
- iCur.reset(); iCur.nPoints = model.points.size();
-// iCur.nTowers = model.towers.size(); iCur.nCubes = model.cubes .size();
-// iCur.nFaces = model.faces .size(); iCur.nStrips = model.strips.size();
-
-// for (Tower t : model.towers) { iCur.tower++;
-// for (Cube c : t.cubes) { iCur.cube ++;
-// for (Face f : c.faces) { iCur.face ++;
-// for (Strip s : f.strips) { iCur.strip++; iCur.isHoriz= (iCur.strip % 2 == 1 || iCur.strip < 5) ? true : false;
- for (Point p : model.points) { iCur.point++;
- xyz P = new xyz(p);
-
- if (s_Spark () > 0) P.y += s_Spark () * (noise(P.x,P.y+NoiseMove/30 ,P.z)*ydMax - ydMax/2.);
- if (s_Wiggle() > 0) P.y += s_Wiggle() * (noise(P.x/(xdMax*.3)-NoiseMove/1500.) - .5) * (ydMax/2.);
-
- color cOld = colors[p.index];
- color cNew = CalcPoint(P);
-
-// if (_Horiz && !iCur.isHoriz) { colors[p.index] = 0; continue; }
-// if (_Vert && iCur.isHoriz) { colors[p.index] = 0; continue; }
- if (_XSym) cNew = blendColor(cNew, CalcPoint(new xyz(xdMax-P.x,P.y,P.z)), ADD);
- if (_YSym) cNew = blendColor(cNew, CalcPoint(new xyz(P.x,ydMax-P.y,P.z)), ADD);
- if (_ZSym) cNew = blendColor(cNew, CalcPoint(new xyz(P.x,P.y,zdMax-P.z)), ADD);
-
- float b = brightness(cNew)/100.;
- b = b < .5 ? pow(b,fSharp) : 1-pow(1-b,fSharp);
-
- float modhue = s_ModHue ()>0 ? s_ModHue ()*360:0;
-
- float noizhue = s_NoiseHue()>0 ? s_NoiseHue()*360*noise( P.x/(xdMax*.3)+NoiseMove/3000.,
- P.y/(ydMax*.3)+NoiseMove/4000.,
- P.z/(zdMax*.3)+NoiseMove/5000.) : 0;
-
- cNew = color( (hue(cNew) + modhue + zSpinHue - noizhue) % 360,
- saturation(cNew) + 100*s_Saturate(),
- 100 * (s_Trails()==0 ? b : max(b, brightness(cOld)/100. - (1-s_Trails()) * deltaMs/200.))
- * (s_Dim ()==0 ? 1 : 1-s_Dim())
- );
-
- colors[p.index] = cNew;
- }
-// }}}}
+ boolean noteOff(Note note) {
+ int row = note.getPitch(), col = note.getChannel();
+ for (int i=0; i<bools.size(); i++) if (bools.get(i).set(row, col, false)) { presetManager.dirty(this); return true; }
+ updateLights(); return false;
}
- void controllerChangeReceived(rwmidi.Controller cc) {
- if (cc.getCC() == 7 && btwn(cc.getChannel(),0,7)) Sliders[cc.getChannel()] = 1.*cc.getValue()/127.;
+ boolean noteOn(Note note) {
+ int row = note.getPitch(), col = note.getChannel();
+ for (int i=0; i<picks.size(); i++) if (picks.get(i).set(row, col)) { presetManager.dirty(this); return true; }
+ for (int i=0; i<bools.size(); i++) if (bools.get(i).set(row, col, true)) { presetManager.dirty(this); return true; }
+ println("row: " + row + " col: " + col); return false;
}
- public float Sliders[] = new float[] {0,0,0,0,0,0,0,0};
- String SliderText[]= new String[] {"Trails", "Dim", "Saturate", "SpinHue", "Hue", "NoiseHue", "Spark", "Wiggle"};
- float s_Trails () { return Sliders[0]; }
- float s_Dim () { return Sliders[1]; }
- float s_Saturate () { return Sliders[2]; }
- float s_SpinHue () { return Sliders[3]; }
- float s_ModHue () { return Sliders[4]; }
- float s_NoiseHue () { return Sliders[5]; }
- float s_Spark () { return Sliders[6]; }
- float s_Wiggle () { return Sliders[7]; }
- _DhP pSharp;
+ void onInactive() { uiDebugText.setText(""); }
+ void onReset() {
+ for (int i=0; i<bools .size(); i++) bools.get(i).reset();
+ for (int i=0; i<picks .size(); i++) picks.get(i).reset();
+ presetManager.dirty(this);
+ updateLights();
+ }
DPat(GLucose glucose) {
super(glucose);
- xyzHalf = new xyz(.5,.5,.5);
- xyz0 = new xyz(0,0,0);
- pSharp = addParam("Shrp", 0);
-
- for (MidiInputDevice input : RWMidi.getInputDevices ()) { if (input.toString().contains("APC")) input .createInput (this);}
- for (MidiOutputDevice output : RWMidi.getOutputDevices()) {
- if (midiout == null && output.toString().contains("APC")) midiout = output.createOutput();
- }
- }
- void UpdateLights() {
- for (int i=0; i<nNumRows ; i++) for (int j=0; j<nNumCols; j++) SetLight(i, j, 0);
- for (int i=0; i<picklist.size() ; i++) {
- Pick P = (Pick)picklist.get(i); SetLight(P.CurRow, P.CurCol, 3);
- }
- SetLight(82, 0, _XSym ? 3 : 0);
- SetLight(83, 0, _YSym ? 3 : 0);
- SetLight(84, 0, _ZSym ? 3 : 0);
- SetLight(85, 0, _RadSym ? 3 : 0);
-// SetLight(86, 0, _Horiz ? 3 : 0);
-// SetLight(87, 0, _Vert ? 3 : 0);
+ pSpark = addParam("Sprk", 0);
+ pWave = addParam("Wave", 0);
+ pTransX = addParam("TrnX", .5);
+ pTransY = addParam("TrnY", .5);
+ pRotX = addParam("RotX", .5);
+ pRotY = addParam("RotY", .5);
+ pRotZ = addParam("RotZ", .5);
+ pSpin = addParam("Spin", .5);
+
+ nPoints = model.points.size();
+ pXsym = new DBool("X-SYM", false, 48, 0); bools.add(pXsym );
+ pYsym = new DBool("Y-SYM", false, 48, 1); bools.add(pYsym );
+ pRsym = new DBool("R-SYM", false, 48, 2); bools.add(pRsym );
+ pXdup = new DBool("X-DUP", false, 48, 3); bools.add(pXdup );
+ pJog = new DBool("JOG" , false, 48, 4); bools.add(pJog );
+ pGrey = new DBool("GREY" , false, 48, 5); bools.add(pGrey );
+
+ modmin = new PVector(model.xMin, model.yMin, model.zMin);
+ mMax = new PVector(model.xMax, model.yMax, model.zMax); mMax.sub(modmin);
+ mCtr = new PVector(); mCtr.set(mMax); mCtr.mult(.5);
+ mHalf = new PVector(.5,.5,.5);
+ xWaveNz = new float[ceil(mMax.y)+1];
+ yWaveNz = new float[ceil(mMax.x)+1];
+
+ //println (model.xMin + " " + model.yMin + " " + model.zMin);
+ //println (model.xMax + " " + model.yMax + " " + model.zMax);
+ //for (MidiOutputDevice o: RWMidi.getOutputDevices()) { if (o.toString().contains("APC")) { APCOut = o.createOutput(); break;}}
}
- Pick GetPick(int row, int col) {
- for (int i=0; i<picklist.size(); i++) { Pick P = (Pick)picklist.get(i);
- if (!btwn(row,P.StartRow,P.EndRow) ) continue;
- if (!btwn(col,0,nNumCols-1) ) continue;
- if (!btwn((row-P.StartRow)*nNumCols + col,0,P.NumPicks-1) ) continue;
- return P;
- }
- return null;
+ float spin() {
+ float raw = val(pSpin);
+ if (raw <= 0.45) {
+ return raw + 0.05;
+ } else if (raw >= 0.55) {
+ return raw - 0.05;
+ }
+ return 0.5;
}
- double Tap1 = 0;
- double getNow() { return millis() + 1000*second() + 60*1000*minute() + 3600*1000*hour(); }
-
- void noteOffReceived(Note note) { if (!bIsActive) return;
- int row = mapRow(note.getPitch()), col = note.getChannel();
-
- if (row == 50 && col == 0 && btwn(getNow() - Tap1,5000,300*1000)) { // hackish tapping mechanism
- double bpm = 32.*60000./(getNow()-Tap1);
- while (bpm < 20) bpm*=2;
- while (bpm > 40) bpm/=2;
- lx.tempo.setBpm(bpm); lx.tempo.trigger(); Tap1=0; println("Tap Set - " + bpm + " bpm");
+ void setAPCOutput(MidiOutput output) {
+ APCOut = output;
+ }
+
+ void updateLights() { if (APCOut == null) return;
+ for (int i = 0; i < NumApcRows; ++i)
+ for (int j = 0; j < 8; ++j) APCOut.sendNoteOn(j, 53+i, 0);
+ for (int i=0; i<picks .size(); i++) APCOut.sendNoteOn(picks.get(i).CurCol, picks.get(i).CurRow, 3);
+ for (int i=0; i<bools .size(); i++) if (bools.get(i).b) APCOut.sendNoteOn (bools.get(i).col, bools.get(i).row, 1);
+ else APCOut.sendNoteOff (bools.get(i).col, bools.get(i).row, 0);
+ }
+
+ void run(double deltaMs)
+ {
+ if (deltaMs > 100) return;
+
+ if (this == midiEngine.getFocusedDeck().getActivePattern()) {
+ String Text1="", Text2="";
+ for (int i=0; i<bools.size(); i++) if (bools.get(i).b) Text1 += " " + bools.get(i).tag + " ";
+ for (int i=0; i<picks.size(); i++) Text1 += picks.get(i).tag + ": " + picks.get(i).CurDesc() + " ";
+ uiDebugText.setText(Text1, Text2);
+ }
+
+ NoiseMove += deltaMs; NoiseMove = NoiseMove % 1e7;
+ StartRun (deltaMs);
+ PVector P = new PVector(), tP = new PVector(), pSave = new PVector();
+ PVector pTrans = new PVector(val(pTransX)*200-100, val(pTransY)*100-50,0);
+ nPoint = 0;
+
+ if (pJog.b) {
+ float tRamp = (lx.tempo.rampf() % .25);
+ if (tRamp < LastJog) xyzJog.set(randctr(mMax.x*.2), randctr(mMax.y*.2), randctr(mMax.z*.2));
+ LastJog = tRamp;
+ }
+
+ // precalculate this stuff
+ float wvAmp = val(pWave), sprk = val(pSpark);
+ if (wvAmp > 0) {
+ for (int i=0; i<ceil(mMax.x)+1; i++)
+ yWaveNz[i] = wvAmp * (noise(i/(mMax.x*.3)-(2e3+NoiseMove)/1500.) - .5) * (mMax.y/2.);
+
+ for (int i=0; i<ceil(mMax.y)+1; i++)
+ xWaveNz[i] = wvAmp * (noise(i/(mMax.y*.3)-(1e3+NoiseMove)/1500.) - .5) * (mMax.x/2.);
}
- UpdateLights();
+ for (LXPoint p : model.points) { nPoint++;
+ setVec(P,p);
+ P.sub(modmin);
+ P.sub(pTrans);
+ if (sprk > 0) {P.y += sprk*randctr(50); P.x += sprk*randctr(50); P.z += sprk*randctr(50); }
+ if (wvAmp > 0) P.y += interpWv(p.x-modmin.x, yWaveNz);
+ if (wvAmp > 0) P.x += interpWv(p.y-modmin.y, xWaveNz);
+ if (pJog.b) P.add(xyzJog);
+
+
+ color cNew, cOld = colors[p.index];
+ { tP.set(P); cNew = CalcPoint(tP); }
+ if (pXsym.b) { tP.set(mMax.x-P.x,P.y,P.z); cNew = blendColor(cNew, CalcPoint(tP), ADD); }
+ if (pYsym.b) { tP.set(P.x,mMax.y-P.y,P.z); cNew = blendColor(cNew, CalcPoint(tP), ADD); }
+ if (pRsym.b) { tP.set(mMax.x-P.x,mMax.y-P.y,mMax.z-P.z); cNew = blendColor(cNew, CalcPoint(tP), ADD); }
+ if (pXdup.b) { tP.set((P.x+mMax.x*.5)%mMax.x,P.y,P.z); cNew = blendColor(cNew, CalcPoint(tP), ADD); }
+ if (pGrey.b) { cNew = lx.hsb(0, 0, lx.b(cNew)); }
+ colors[p.index] = cNew;
+ }
}
+}
+//----------------------------------------------------------------------------------------------------------------------------------
+class dTurn {
+ dVertex v;
+ int pos0, pos1;
+ dTurn(int _pos0, dVertex _v, int _pos1) { v = _v; pos0 = _pos0; pos1 = _pos1; }
+}
- boolean _XSym=false, _YSym=false, _ZSym=false, _RadSym=false; //, _Horiz=false, _Vert=false;
-
- void noteOnReceived (Note note) { if (!bIsActive) return;
- int row = mapRow(note.getPitch()), col = note.getChannel();
- Pick P = GetPick(row,col);
- if (P != null) { P.CurRow=row; P.CurCol=col; }
- else if (row == 50 && col == 0) { lx.tempo.trigger(); Tap1 = getNow(); }
- else if (row == 82 && col == 0) _XSym = !_XSym ;
- else if (row == 83 && col == 0) _YSym = !_YSym ;
- else if (row == 84 && col == 0) _ZSym = !_ZSym ;
- else if (row == 85 && col == 0) _RadSym = !_RadSym ;
- else keypad(row, col) ;
+class dVertex {
+ dVertex c0, c1, c2, c3, // connections on the cube
+ opp, same; // opp - same strip, opp direction
+ // same - same strut, diff strip, dir
+ dTurn t0, t1, t2, t3;
+ Strip s;
+ int dir, ci; // dir -- 1 or -1.
+ // ci -- color index
+
+ dVertex(Strip _s, LXPoint _p) { s = _s; ci = _p.index; }
+ LXPoint getPoint(int i) { return s.points.get(dir>0 ? i : 15-i); }
+ void setOpp(dVertex _opp) { opp = _opp; dir = (ci < opp.ci ? 1 : -1); }
+}
+//----------------------------------------------------------------------------------------------------------------------------------
+class dPixel { dVertex v; int pos; dPixel(dVertex _v, int _pos) { v=_v; pos=_pos; } }
+class dLattice {
+ void addTurn (dVertex v0, int pos0, dVertex v1, int pos1) { dTurn t = new dTurn(pos0, v1, pos1);
+ if (v0.t0 == null) { v0.t0=t; return; }
+ if (v0.t1 == null) { v0.t1=t; return; }
+ if (v0.t2 == null) { v0.t2=t; return; }
+ if (v0.t3 == null) { v0.t3=t; return; }
+ }
+ float dist2 (Strip s1, int pos1, Strip s2, int pos2) { return pointDist(s1.points.get(pos1), s2.points.get(pos2)); }
+ float pd2 (LXPoint p1, float x, float y, float z) { return dist(p1.x,p1.y,p1.z,x,y,z); }
+ boolean sameSame (Strip s1, Strip s2) { return max(dist2(s1, 0, s2, 0), dist2(s1,15, s2,15)) < 5 ; } // same strut, same direction
+ boolean sameOpp (Strip s1, Strip s2) { return max(dist2(s1, 0, s2,15), dist2(s1,15, s2,0 )) < 5 ; } // same strut, opp direction
+ boolean sameBar (Strip s1, Strip s2) { return sameSame(s1,s2) || sameOpp(s1,s2); } // 2 strips on same strut
+
+
+ void addJoint (dVertex v1, dVertex v2) {
+ // should probably replace parallel but further with the new one
+ if (v1.c0 != null && sameBar(v2.s, v1.c0.s)) return;
+ if (v1.c1 != null && sameBar(v2.s, v1.c1.s)) return;
+ if (v1.c2 != null && sameBar(v2.s, v1.c2.s)) return;
+ if (v1.c3 != null && sameBar(v2.s, v1.c3.s)) return;
+
+ if (v1.c0 == null) v1.c0 = v2;
+ else if (v1.c1 == null) v1.c1 = v2;
+ else if (v1.c2 == null) v1.c2 = v2;
+ else if (v1.c3 == null) v1.c3 = v2;
}
- _DhP addParam(String label, double value) {
- _DhP P = new _DhP(label, value);
- super.addParameter(P);
- paramlist.add(P); return P;
+ dVertex v0(Strip s) { return (dVertex)s.obj1; }
+ dVertex v1(Strip s) { return (dVertex)s.obj2; }
+
+ dPixel getClosest(PVector p) {
+ dVertex v = null; int pos=0; float d = 500;
+
+ for (Strip s : glucose.model.strips) {
+ float nd = pd2(s.points.get(0),p.x,p.y,p.z); if (nd < d) { v=v0(s); d=nd; pos=0; }
+ if (nd > 30) continue;
+ for (int k=0; k<=15; k++) {
+ nd = pd2(s.points.get(k),p.x,p.y,p.z); if (nd < d) { v =v0(s); d=nd; pos=k; }
+ }
+ }
+ return random(2) < 1 ? new dPixel(v,pos) : new dPixel(v.opp,15-pos);
}
-
- Pick addPick(String name, int def, int nmax) {
- Pick P = new Pick(name, def, nmax);
- P.StartRow = nMaxRow;
- P.EndRow = P.StartRow + int((nmax-1) / nNumCols);
- nMaxRow = P.EndRow + 1;
- P.CurCol = def % nNumCols;
- P.CurRow = P.StartRow + def/nNumCols;
- picklist.add(P);
- return P;
+
+ dLattice() {
+ lattice=this;
+
+ for (Strip s : glucose.model.strips) {
+ dVertex vrtx0 = new dVertex(s,s.points.get(0 )); s.obj1=vrtx0;
+ dVertex vrtx1 = new dVertex(s,s.points.get(15)); s.obj2=vrtx1;
+ vrtx0.setOpp(vrtx1); vrtx1.setOpp(vrtx0);
+ }
+
+ for (Strip s1 : glucose.model.strips) { for (Strip s2 : glucose.model.strips) {
+ if (s1.points.get(0).index < s2.points.get(0).index) continue;
+ int c=0;
+ if (sameSame(s1,s2)) { v0(s1).same = v0(s2); v1(s1).same = v1(s2);
+ v0(s2).same = v0(s1); v1(s2).same = v1(s1); continue; } // parallel
+ if (sameOpp (s1,s2)) { v0(s1).same = v1(s2); v1(s1).same = v0(s2);
+ v0(s2).same = v1(s1); v1(s2).same = v0(s1); continue; } // parallel
+ if (dist2(s1, 0, s2, 0) < 5) { c++; addJoint(v1(s1), v0(s2)); addJoint(v1(s2), v0(s1)); }
+ if (dist2(s1, 0, s2,15) < 5) { c++; addJoint(v1(s1), v1(s2)); addJoint(v0(s2), v0(s1)); }
+ if (dist2(s1,15, s2, 0) < 5) { c++; addJoint(v0(s1), v0(s2)); addJoint(v1(s2), v1(s1)); }
+ if (dist2(s1,15, s2,15) < 5) { c++; addJoint(v0(s1), v1(s2)); addJoint(v0(s2), v1(s1)); }
+ if (c>0) continue;
+
+ // Are they touching at all?
+ int pos1=0, pos2=0; float d = 100;
+
+ while (pos1 < 15 || pos2 < 15) {
+ float oldD = d;
+ if (pos1<15) { float d2 = dist2(s1, pos1+1, s2, pos2+0); if (d2 < d) { d=d2; pos1++; } }
+ if (pos2<15) { float d2 = dist2(s1, pos1+0, s2, pos2+1); if (d2 < d) { d=d2; pos2++; } }
+ if (d > 50 || oldD == d) break ;
+ }
+
+ if (d>5) continue;
+ addTurn(v0(s1), pos1, v0(s2), pos2); addTurn(v1(s1), 15-pos1, v0(s2), pos2);
+ addTurn(v0(s2), pos2, v0(s1), pos1); addTurn(v1(s2), 15-pos2, v0(s1), pos1);
+ }}
}
}
+
+dLattice lattice;
//----------------------------------------------------------------------------------------------------------------------------------