//----------------------------------------------------------------------------------------------------------------------------------
-float xdMax,ydMax,zdMax;
-int NumApcRows = 5, NumApcCols = 8;
-DGlobals DG = new DGlobals();
-
-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; }
+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; }
+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, String d[]) { NumPicks=_Max; Default = _Def; tag=label; Desc = d; }
- int Cur() { return (CurRow-StartRow)*NumApcCols + CurCol; }
- int NumPicks, Default, CurRow, CurCol, StartRow, EndRow;
- String Desc[] ;
- String tag ;
-}
-//----------------------------------------------------------------------------------------------------------------------------------
-public class _DhP extends BasicParameter {
- double dflt;
- _DhP (String label, double value) { super(label,value); dflt=value; }
- void Set (double value) { super.setValue(value); }
- void reset () { super.setValue(dflt); }
- float Val () { return getValuef(); }
- boolean ZeroOrOne () { return Val()==0 || Val() == 1; }
-}
-//----------------------------------------------------------------------------------------------------------------------------------
-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(Point p ) {x=p.fx ; y=p.fy; z=p.fz;}
- 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 ); }
- boolean isZero () {return x==0 && y==0 && z==0; }
-
- void RotateZ (xyz o, float nSin, float nCos) {
- float nX = nCos*(x-o.x) - nSin*(y-o.y) + o.x;
- float nY = nSin*(x-o.x) + nCos*(y-o.y) + o.y;
- x = nX; y = nY;
+ 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();
}
- void RotateX (xyz o, float nSin, float nCos) {
- float nY = nCos*(y-o.y) - nSin*(z-o.z) + o.y;
- float nZ = nSin*(y-o.y) + nCos*(z-o.z) + o.z;
- y = nY; z = nZ;
- }
+ int Cur() { return (CurRow-StartRow)*NumApcCols + CurCol; }
+ String CurDesc() { return Desc[Cur()]; }
+ void reset() { CurCol = Default % NumApcCols; CurRow = StartRow + Default / NumApcCols; }
- void RotateY (xyz o, float nSin, float nCos) {
- float nZ = nCos*(z-o.z) - nSin*(x-o.x) + o.z;
- float nX = nSin*(z-o.z) + nCos*(x-o.x) + o.x;
- z = nZ; x = nX;
+ 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;
}
-
- 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 DGlobals {
- boolean bInit = false;
- MidiOutput APCOut = null;
- MidiInput APCIn = null, OxygenIn = null;
- DPat CurPat = null, NextPat = null;
- boolean _XSym = false, _YSym = false,
- _ZSym = false, _RSym = false;
- String Text1 = "", Text2 = "";
-
- float Sliders[] = new float[] {0,0,0,0,0,0,0,0};
- String SliderText[] = new String[] {"Trails", "Dim", "Saturate", "SpinHue", "Hue", "NoiseHue", "Spark", "Wiggle"};
-
- 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 (APCOut != null) APCOut.sendNoteOn(col, unmapRow(row), clr); }
- void SetKnob (int cc , int chan,int val){ if (APCOut != null) APCOut.sendController(cc , chan , val); }
-
- float _Trails () { return Sliders[0]; }
- float _Dim () { return Sliders[1]; }
- float _Saturate () { return Sliders[2]; }
- float _SpinHue () { return Sliders[3]; }
- float _ModHue () { return Sliders[4]; }
- float _NoiseHue () { return Sliders[5]; }
- float _Spark () { return Sliders[6]; }
- float _Wiggle () { return Sliders[7]; }
-
- void Init () {
- if (bInit) return; bInit=true;
- for (MidiOutputDevice output : RWMidi.getOutputDevices()) {
- if (APCOut == null && output.toString().contains("APC")) APCOut = output.createOutput();
- }
- for (MidiInputDevice input : RWMidi.getInputDevices ()) {
- if (input.toString().contains("APC")) input.createInput (this);
- }
+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
+{
+ ArrayList<Pick> picks = new ArrayList<Pick> ();
+ ArrayList<DBool> bools = new ArrayList<DBool> ();
- void SetText()
- {
- Text1 = ""; Text2 = "";
- Text1 += " XSym: " + (_XSym ? "ON" : "OFF") + " ";
- Text1 += " YSym: " + (_YSym ? "ON" : "OFF") + " ";
- Text1 += " ZSym: " + (_ZSym ? "ON" : "OFF") + " ";
- Text1 += " RSym: " + (_RSym ? "ON" : "OFF") + " ";
- for (int i=0; i<CurPat.picks.size(); i++) {
- Pick P = (Pick)CurPat.picks.get(i); Text1 += P.tag + ": " + P.Desc[P.Cur()] + " ";
- }
-
- Text2 = "SLIDERS: ";
- for (int i=0; i<8; i++) if (SliderText[i] != "") {
- Text2 += SliderText[i] + ": " + int(100*Sliders[i]) + " "; }
+ PVector mMax, mCtr, mHalf;
- uiDebugText.setText(Text1, Text2);
+ MidiOutput APCOut;
+ int nMaxRow = 53;
+ float LastJog = -1;
+ float[] xWaveNz, yWaveNz;
+ int nPoint , nPoints;
+ PVector xyzJog = new PVector(), modmin;
+
+ 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 controllerChangeReceived(rwmidi.Controller cc) {
- if (cc.getCC() == 7 && btwn(cc.getChannel(),0,7)) { Sliders[cc.getChannel()] = 1.*cc.getValue()/127.; }
- else if (cc.getCC() == 15 && cc.getChannel() == 0) {
- lx.engine.getDeck(1).getCrossfader().setValue( 1.*cc.getValue()/127.);
- }
-
- //else { println(cc.getCC() + " " + cc.getChannel() + " " + cc.getValue()); }
+ 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 Deactivate (DPat p) { if (p == CurPat) { uiDebugText.setText(""); CurPat = NextPat; } NextPat = null; }
- void Activate (DPat p) {
- NextPat = CurPat; CurPat = p;
- while (lx.tempo.bpm() > 40) lx.tempo.setBpm(lx.tempo.bpm()/2);
- for (int i=0; i<p.paramlist.size(); i++) ((_DhP)p.paramlist.get(i)).reset();
- UpdateLights();
+ 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;
}
- void UpdateLights() {
- for (int i=0; i<NumApcRows ; i++) for (int j=0; j<NumApcCols; j++) SetLight(i, j, 0);
- for (int i=48;i< 56 ; i++) SetKnob(0, i, 0);
- for (int i=16;i< 20 ; i++) SetKnob(0, i, 0);
- for (int i=0; i<CurPat.picks.size() ; i++) {
- Pick P = (Pick)CurPat.picks.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, _RSym ? 3 : 0);
-
- for (int i=0; i<CurPat.paramlist.size(); i++) {
- _DhP Param = (_DhP)CurPat.paramlist.get(i);
- SetKnob ( 0, i<=55 ? 48+i : 16 + i - 8, int(Param.Val()*127) );
- }
+ 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();
}
-
- double Tap1 = 0;
- double getNow() { return millis() + 1000*second() + 60*1000*minute() + 3600*1000*hour(); }
- void noteOffReceived(Note note) {
- if (CurPat == null) return;
- int row = DG.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");
- }
- UpdateLights();
+ DPat(GLucose glucose) {
+ super(glucose);
+
+ 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;}}
}
- void noteOnReceived (Note note) {
- if (CurPat == null) return;
- int row = mapRow(note.getPitch()), col = note.getChannel();
-
- 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) _RSym = !_RSym ;
- else {
- for (int i=0; i<CurPat.picks.size(); i++) { Pick P = (Pick)CurPat.picks.get(i);
- if (!btwn(row,P.StartRow,P.EndRow) ) continue;
- if (!btwn(col,0,NumApcCols-1) ) continue;
- if (!btwn((row-P.StartRow)*NumApcCols + col,0,P.NumPicks-1) ) continue;
- P.CurRow=row; P.CurCol=col; return;
- }
- //println(row + " " + col);
- }
+ 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;
}
-}
-//----------------------------------------------------------------------------------------------------------------------------------
-public class DPat extends SCPattern
-{
- ArrayList picks = new ArrayList();
- ArrayList paramlist = new ArrayList();
- int nMaxRow = 0;
- float zSpinHue = 0;
- int nPoint , nPoints;
- xyz xyzHalf = new xyz(.5,.5,.5),
- xyzdMax = new xyz(),
- xyzMid = new xyz();
- float NoiseMove = random(10000);
- _DhP pSharp, pRotX, pRotY, pRotZ;
- 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)); }
- 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))) ) )); }
- void StartRun(double deltaMs) { }
- color CalcPoint(xyz p) { return color(0,0,0); }
- boolean IsActive() { return this == DG.CurPat; }
- void onInactive() { DG.Deactivate(this); }
- void onActive () { DG.Activate(this); }
-
- _DhP addParam(String label, double value) {
- _DhP P = new _DhP(label, value);
- super.addParameter(P);
- paramlist.add(P); return P;
- }
-
- Pick addPick(String name, int def, int nmax, String[] desc) {
- Pick P = new Pick(name, def, nmax, desc);
- P.StartRow = nMaxRow;
- P.EndRow = P.StartRow + int((nmax-1) / NumApcCols);
- nMaxRow = P.EndRow + 1;
- P.CurCol = def % NumApcCols;
- P.CurRow = P.StartRow + def / NumApcCols;
- picks.add(P);
- return P;
+ void setAPCOutput(MidiOutput output) {
+ APCOut = output;
}
- DPat(GLucose glucose) {
- super(glucose);
- DG.Init();
- pSharp = addParam("Shrp" , 0);
- nPoints = model.points.size();
- xdMax = model.xMax;
- ydMax = model.yMax;
- zdMax = model.zMax;
- xyzdMax = new xyz(xdMax,ydMax,zdMax);
- xyzMid = new xyz(xdMax/2, ydMax/2, zdMax/2);
+ 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)
{
- NoiseMove += deltaMs;
- StartRun (deltaMs);
- zSpinHue += DG._SpinHue ()*deltaMs*.05;
- xyz P = new xyz();
- float modhue = DG._ModHue ()==0 ? 0 : DG._ModHue ()*360;
- float fSharp = 1/(1.01-pSharp.Val());
+ if (deltaMs > 100) return;
- DG.SetText();
+ 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;
- for (Point p : model.points) { nPoint++;
- if (!IsActive()) { colors[p.index] = color(0,0,0); continue; }
- P.set(p);
+ 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.);
+ }
+
+ 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; }
+}
- if (DG._Spark () > 0) P.y += DG._Spark () * (noise(P.x,P.y+NoiseMove/30 ,P.z)*ydMax - ydMax/2.);
- if (DG._Wiggle() > 0) P.y += DG._Wiggle() * (noise(P.x/(xdMax*.3)-NoiseMove/1500.) - .5) * (ydMax/2.);
+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;
+ }
- color cOld = colors[p.index];
+ dVertex v0(Strip s) { return (dVertex)s.obj1; }
+ dVertex v1(Strip s) { return (dVertex)s.obj2; }
- color cNew = CalcPoint(P);
- if (DG._XSym) cNew = blendColor(cNew, CalcPoint(new xyz(xdMax-P.x,P.y,P.z)), ADD);
- if (DG._YSym) cNew = blendColor(cNew, CalcPoint(new xyz(P.x,ydMax-P.y,P.z)), ADD);
- if (DG._ZSym) cNew = blendColor(cNew, CalcPoint(new xyz(P.x,P.y,zdMax-P.z)), ADD);
+ dPixel getClosest(PVector p) {
+ dVertex v = null; int pos=0; float d = 500;
- float b = brightness(cNew)/100.;
- b = b < .5 ? pow(b,fSharp) : 1-pow(1-b,fSharp);
+ 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);
+ }
- float noizhue = DG._NoiseHue()==0 ? 0 : DG._NoiseHue()*360*noise(
- P.x/(xdMax*.3)+NoiseMove*.0003,
- P.y/(ydMax*.3)+NoiseMove*.00025,
- P.z/(zdMax*.3)+NoiseMove*.0002 );
+ dLattice() {
+ lattice=this;
- cNew = color( (hue(cNew) + modhue + zSpinHue - noizhue) % 360,
- saturation(cNew) + 100*DG._Saturate(),
- 100 * (DG._Trails()==0 ? b : max(b, (float) (brightness(cOld)/100. - (1-DG._Trails()) * deltaMs/200.)))
- * (DG._Dim ()==0 ? 1 : 1-DG._Dim())
- );
-
- colors[p.index] = cNew;
+ 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;
//----------------------------------------------------------------------------------------------------------------------------------