Mercurial > hg > soniczoomios
diff grid.mm @ 38:0dfe9e0c01aa
Evnt trails fit with uploads. Smooth button.
author | Robert Tubb <rt300@eecs.qmul.ac.uk> |
---|---|
date | Wed, 10 Apr 2013 18:57:05 +0100 |
parents | 8ed7522deaaa |
children | df7c08faf541 |
line wrap: on
line diff
--- a/grid.mm Tue Apr 09 17:14:31 2013 +0100 +++ b/grid.mm Wed Apr 10 18:57:05 2013 +0100 @@ -26,7 +26,7 @@ } void Grid::init(){ - interpolateMode = INTERPOLATE_GRID; + interpolateMode = NO_INTERPOLATION; maxZoom = false; minZoom = false; @@ -66,32 +66,27 @@ return (T(0) < val) - (val < T(0)); } //-------------------------------------------------------------- -int Grid::calculateInterpolateLevel(){ +double Grid::calculateInterpolateLevel(){ if(interpolateMode == INTERPOLATE_GRID){ - // calculate according to smallest gridlines - // exactly same algorithm as for drawing lines - // i.e. kinda duplicated code. - float markpow = pow(paramsPerDim,2.0); - for(int p = 0; p < paramBitDepth; p++){ - - double gridSize = pow(markpow,p); - double divsr = size.x / gridSize; - - // return the spacing - if( ofGetWidth()/divsr >= smallestGridSpacing){ - interpLevel = p; - return p; - } - } - interpLevel = 0; - return 0; + + // log_32 of scale times the pixel size we want to be the "integral" interp + int N = 1 << paramsPerDim; + interpLevel = log(scale*N*smallestGridSpacing)/log(N); + + return interpLevel; }else{ interpLevel = 0; return 0; // ??? } } //-------------------------------------------------------------- - +void Grid::setInterpolation(interpolateModeType mode){ + interpolateMode = mode; + viewWasChanged(); + calculateInterpolateLevel(); + eventLogger.clearTrail(); +} +//-------------------------------------------------------------- void Grid::draw(){ if(interpolateMode == NO_INTERPOLATION){ drawGridLines(); @@ -416,8 +411,15 @@ } //-------------------------------------------------------------- void Grid::snapCheck(){ + + if(interpolateMode == INTERPOLATE_GRID){ + snapped = false; + closestPreset = NULL; + snapCentre = centre; + return; + } // no presets visible + // check environs for presets. - vector<Preset *> closePresets = presetManager.getPresetsInRange(centre - snapDist*scale, centre + snapDist*scale); if(closePresets.size() > 0){ snapped = true; @@ -647,24 +649,44 @@ vector<int> Grid::calculateInterpolatedParamsFromCoord(TwoVector coord){ vector<int> result; - // round by masking according to interpLevel + int interpLevelBigGrid = ceil(interpLevel); + int interpLevelSmallGrid = floor(interpLevel); + + if(interpLevelBigGrid >= paramBitDepth){ + // maximum is bit-1 so don't do interp at all + vector<int> pSmallGrid = interpHilbert(interpLevelSmallGrid, coord); + return pSmallGrid; + } + double interpFrac = interpLevel - interpLevelSmallGrid; + + vector<int> pBigGrid = interpHilbert(interpLevelBigGrid, coord); + vector<int> pSmallGrid = interpHilbert(interpLevelSmallGrid, coord); +// now we need to interpolate twixt these two aswell! + + result = interpVector(pBigGrid, pSmallGrid, interpFrac); + + return result; +} +//-------------------------------------------------------------- +vector<int> Grid::interpHilbert(int bitlevel, TwoVector coord){ + vector<int> result; long long x = coord.x; long long y = coord.y; - cout << interpLevel << "\n"; - int roundDigits = (paramsPerDim*interpLevel); + + int roundDigits = (paramsPerDim*bitlevel); // knock off last digits x = x >> roundDigits; x = x << roundDigits; float frac = (coord.x - x)/(1 << roundDigits); long long xlower = x; long long xupper = x + (1 << roundDigits); - + vector<int> pupper = hilbert.calculateParamsFromIndex(xupper); vector<int> plower = hilbert.calculateParamsFromIndex(xlower); result = interpVector(pupper,plower,frac); -// now Y + // now Y y = y >> roundDigits; y = y << roundDigits; frac = (coord.y - y)/(1 << roundDigits); @@ -675,8 +697,9 @@ plower = hilbert.calculateParamsFromIndex(ylower); vector<int> resultY = interpVector(pupper,plower,frac); -// stickem together + // stickem together result.insert( result.end(), resultY.begin(), resultY.end() ); + return result; } //-------------------------------------------------------------- @@ -720,4 +743,354 @@ } //-------------------------------------------------------------- //-------------------------------------------------------------- -//-------------------------------------------------------------- \ No newline at end of file +//-------------------------------------------------------------- + + +//-------------------------------------------------------------- +//-------------------------------------------------------------- +//-------------------------------------------------------------- +//-------------------------------------------------------------- +//-------------------------------------------------------------- +#pragma mark The old algorithm + +TwoVector Grid::calculateCoordFromParamsOld(vector<int> params) const{ + + vector<int> ccValueX(paramsPerDim); + vector<int> ccValueY(paramsPerDim); + for(int i=0;i<paramsPerDim;i++){ + ccValueX[i] = params[i]; + ccValueY[i] = params[i+paramsPerDim]; + } + vector<vector <bool> > codesX = midiToGray(ccValueX); + vector<vector <bool> > codesY = midiToGray(ccValueY); + + vector<int> base32X = codesToBase32(codesX); + vector<int> base32Y = codesToBase32(codesY); + + TwoVector result; + result.x = base32toCoord(base32X); + result.y = base32toCoord(base32Y); + return result; +} + +//-------------------------------------------------------------- +vector<int> Grid::calculateParamsFromCoordOld(TwoVector coord) const{ + // some arrays in reverse order of power from normal numbers! 1,2,4, + + // centre to base 32 + if (coord.x > maxValue || coord.y > maxValue){ + cout << "calculateParams Error: centre double value is too large" << "\n"; + vector<int> empty; + return empty; + } + + //-------------------------- + // X + vector<int> base32x = coordTobase32(coord.x); // 7 numbers from 0 to 31 + vector<vector <bool> > grayCodesX; + + int size = base32x.size(); + for(int i=0;i<size;i++){ + grayCodesX.push_back(intToGray(base32x[i])); + } + + vector<int> result; + result = grayToMidi(grayCodesX); + //-------------------------- + // AND FOR Y + vector<int> base32y = coordTobase32(coord.y); + vector<vector <bool> > grayCodesY; + + size = base32y.size(); + for(int i=0;i<size;i++){ + grayCodesY.push_back(intToGray(base32y[i])); + } + + vector<int> resultY; + resultY = grayToMidi(grayCodesY); + + // concatenate + result.insert( result.end(), resultY.begin(), resultY.end() ); + return result; +} +//------------------------------------------------------------------- + +// for 1 dimension!!! i.e. call this twice +vector<int> Grid::grayToMidi(vector<vector <bool> > grayCodes) const{ + + // gray to midi CC values + // loop thru the scales to build up a CC number per dimension + int midiCCresult[paramsPerDim]; // TODO dims specific + for(int i=0;i<paramsPerDim;i++){ + midiCCresult[i] = 0; + } + + int bin = 1; + bin = bin << grayCodes.size()-1; + + int midP = 0; + + vector<vector <bool> >::iterator piter = grayCodes.begin(); + for(;piter < grayCodes.end();piter++){ // each lesser power of 2 + midP = 0; // reset + vector<bool>::iterator diter = (*piter).begin(); + for(; diter <= (*piter).end();diter++){ // each one is different dimension + int ig = int(*diter); // convert binary to int + //cout << "ig: " << ig; + midiCCresult[midP] += ig*bin; // mult by power of two + midP++; + } + bin = bin >> 1; // next power of 2 down + + } + + // put in vector + vector<int> result; + for(int i=0;i<paramsPerDim;i++){ + result.push_back(midiCCresult[i]); + } + + return result; + + +} + + +//-------------------------------------------------------------- + +vector<bool> Grid::intToGray(int num, int dimToTravel) const{ + + // dimToTravel - this is the dimension that we want the walk to traverse, i.e. the last non zero digit of the code + // so swap it for 3 to produce correct orientation + + // just use look up table... until it gets huuuge. + vector<bool> grayCode = vcode[num]; + grayCode[3] = vcode[num][dimToTravel]; + grayCode[dimToTravel] = vcode[num][3]; + return grayCode; +} +//-------------------------------------------------------------- +/* + breaks down float into a base 32 number (2^D) + each of these is converted to gray code + this is then converted to 10 parameters, where each 32-digit becomes separate power of 2 + so "zoom" grid 32-patches are converted to 2-scales. 1,2,4,8,16,32,64,(128?) biggest number is 32^7 + */ +vector<int> Grid::coordTobase32(double value) const{ + //double base = 32.0; + if(value < 0.0){ + cout << "coordTobase32 error: input value is negative\n"; + value = 0.0; + }else if(value > maxValue){ + cout << "coordTobase32 error: input value too big!\n"; + } + double rem, divdr = 0.0; + int digit32; + + // what power of 32 to start at? + int maxpow = 7; // midi cc specific + vector<int> result; + + rem = value; + for(;maxpow >=0;maxpow--){ + // repeatedly get digit and remainder. This is exactly what we're doing in draw !?... could put all this in one place? + divdr = pow((double)codeLength,(double)maxpow); + digit32 = floor(rem/divdr); + rem = rem - digit32*divdr; + result.push_back(digit32); // array, biggest index is smallest power + } + // at this point rem should be fractional... use for interp? + + return result; +} +//-------------------------------------------------------------- + +vector<int> Grid::codesToBase32(vector<vector<bool> > inCodes) const{ + vector<int> result; + for(int i=0;i<paramBitDepth;i++){ + result.push_back(grayToInt(inCodes[i])); + } + return result; +} +//-------------------------------------------------------------- + +int Grid::grayToInt(vector<bool> incode) const{ + // look for match in table + + int s = vcode.size(); + + for(int i=0; i<s;i++){ // fill vector + if(vcode[i] == incode){ + return i; + } + + } + cout << "grayToInt error: no matching code found!"; + return -1; +} +//-------------------------------------------------------------- +double Grid::base32toCoord(vector<int> base32Digs) const{ + // build up the big float from a base 32 number + double result = 0.0; + + // what power of 32 to start at? + int mpow = base32Digs.size() - 1; // should be 7... + + for(int p=0;p<=mpow;p++){ // biggest index is smallest power + result += ((double)base32Digs[p]) * pow(32.0, (double)mpow-p); + + } + return result; + +} +//-------------------------------------------------------------- +// for 1 dimension - takes in 5 cc params and outputs 7 codes +vector<vector <bool> > Grid::midiToGray(vector<int> ccValue) const{ + int pow2 = 1 << (paramBitDepth-1); + + vector<int> aCode(paramsPerDim); + vector<vector<int> > theXCodes(paramBitDepth,aCode); + + // build up binary gray code representations from the bits of the midi ccs + + vector<vector<bool> > theCodes(paramBitDepth, vector<bool>(paramsPerDim)); + + // x + for(int p=0;p<paramBitDepth;p++){ + + for(int i=0;i<paramsPerDim;i++){ + + bool bit = (pow2 == (ccValue[i] & pow2)); + theCodes[p][i] = bit; + } + pow2 = pow2 >> 1; + + } + return theCodes; +} + +//-------------------------------------------------------------- +void Grid::makeCode(){ + + ////////////////////////////////~~~,,,,,,,,......... + ////////// gray code generation + ////// + /// + // TODO 5bit specific + // transition sequence.... what a palaver! only need to do once though. + + // max MRL + int trans[] = {0,1,2,3,0,4,2,1,0,3,2,1,0,4,2,3,0,1,2,3,0,4,2,1,0,3,2,1,0,4,2,3}; + // balanced + int transB[] = {1,2,3,4,5,1,5,2,3,5,2,4,2,3,4,1,4,3,2,3,1,5,3,4,1,5,2,5,3,4,1,3}; + for(int i = 0; i<codeLength; i++){ + transB[i] = transB[i] - 1; + } + + int code[codeLength][paramsPerDim]; // start with normal array + + + + for(int j=0; j<paramsPerDim; j++){ + code[0][j] = 0; + } + + for(int i=0; i < codeLength-1; i++){ // don't need last 3 + transSeq.push_back(trans[i]); // member vector + for(int j=0; j<paramsPerDim; j++){ + + if (j == abs(trans[i])){ + code[i+1][j] = !code[i][j]; + }else{ + code[i+1][j] = code[i][j]; + } + } + + } + + for(int i=0; i < codeLength; i++){ // fill vector + + vcode.push_back(vector<bool>()); + + for(int j=0; j<paramsPerDim; j++){ + vcode[i].push_back(code[i][j]); + } + } + /* + // now try with iterators to print... + vector< vector<bool> >::iterator cit; + //vector<bool>::iterator bit; + vector<bool>::iterator bit; + int i = 0; + for(cit=vcode.begin(); cit!=vcode.end() ; cit++){ // fill vector + i++; + cout << i << " = "; + bit = (*cit).begin(); + for(bit=(*cit).begin(); bit!=(*cit).end() ; bit++){ + + cout << *bit; + } + cout << "\n"; + + } + + // codeToInt unit test + vector<bool> aCode = vcode[12]; + int result = grayToInt(aCode); + cout << "GRAY TO INT : " << result << "\n"; + + cout << "-------------------------------\n"; + + // base32toFloat unit test + + vector<int> test32 = coordTobase32(869437.0); + double cresult = base32toCoord(test32); + cout << "base32toCoord : " << cresult << "\n"; + + cout << "-------------------------------\n"; + + + + // midiToGray unit test + + vector<vector<bool> > incodes(paramBitDepth, vector<bool>(paramsPerDim)); + for(int i=0;i<7;i++){ + incodes[i] = vcode[i+5]; + } + + vector<int> midiTest; + midiTest = grayToMidi(incodes); + vector<vector<bool> > outcodes = midiToGray(midiTest); + + vector< vector<bool> >::iterator cit1; + //vector<bool>::iterator bit; + vector<bool>::iterator bit1; + cout << "midiToGray Unit test\n"; + for(int i=0;i<paramBitDepth;i++){ // fill vector + + for(int j=0;j<paramsPerDim;j++){ + + cout << (incodes[i][j] == outcodes[i][j]) << ","; + } + cout << "\n"; + + } + cout << "-------------------------------\n"; + + + // whole process unit test(?) + + TwoVector inCoord(888999777,777666555); + vector<int> checkParam; + checkParam = calculateParamsFromCoord(inCoord); + for(int i=0; i<2*paramsPerDim;i++){ + cout << checkParam[i] << "_"; + } + TwoVector outCoord = calculateCoordFromParams(checkParam); + cout << "Unit TEst coord = " << outCoord.x << "," << outCoord.y << "\n"; + */ + +} +//-------------------------------------------------------------- +//-------------------------------------------------------------- +//--------------------------------------------------------------