| 1 |
|
|---|
| 2 |
// |
|---|
| 3 |
// This was a test for a matrix-math-based continuous pan/zoom set-up for |
|---|
| 4 |
// Modest Maps, which works, and has subsequently been turned into a library. |
|---|
| 5 |
// |
|---|
| 6 |
// There may be bugs in this sketch, and they won't be fixed. |
|---|
| 7 |
// |
|---|
| 8 |
// I didn't get around to doing rotations. |
|---|
| 9 |
// |
|---|
| 10 |
|
|---|
| 11 |
// pan, zoom and rotate |
|---|
| 12 |
float tx = 0, ty = 0; |
|---|
| 13 |
float sc = 1; |
|---|
| 14 |
float a = 0.0; |
|---|
| 15 |
|
|---|
| 16 |
PFont f; |
|---|
| 17 |
|
|---|
| 18 |
void setup() { |
|---|
| 19 |
size(500, 300); |
|---|
| 20 |
|
|---|
| 21 |
tx = -128; |
|---|
| 22 |
ty = -128; |
|---|
| 23 |
|
|---|
| 24 |
f = createFont("Helvetica",16); |
|---|
| 25 |
} |
|---|
| 26 |
|
|---|
| 27 |
void draw() { |
|---|
| 28 |
background(0); |
|---|
| 29 |
|
|---|
| 30 |
pushMatrix(); |
|---|
| 31 |
translate(width/2, height/2); |
|---|
| 32 |
scale(sc,sc); |
|---|
| 33 |
rotate(radians(a)); |
|---|
| 34 |
translate(tx,ty); |
|---|
| 35 |
|
|---|
| 36 |
float minX = screenX(0,0); |
|---|
| 37 |
float minY = screenY(0,0); |
|---|
| 38 |
float maxX = screenX(256,256); |
|---|
| 39 |
float maxY = screenY(256,256); |
|---|
| 40 |
|
|---|
| 41 |
// println("map: " + nf(minX,1,3) + " " + nf(minY,1,3) + " : " + nf(maxX,1,3) + " " + nf(maxY,1,3)); |
|---|
| 42 |
|
|---|
| 43 |
// do the diagonal because we might rotate |
|---|
| 44 |
float sideLength = dist(minX, minY, maxX, maxY); |
|---|
| 45 |
float zoom0Length = dist(0,0,256,256); // yes I should hard-code this |
|---|
| 46 |
// println(zoom0Length + " --> " + sideLength); |
|---|
| 47 |
|
|---|
| 48 |
// 0 when sideLength == 256, 1 when sideLength == 512, 2 when sideLength == 1024 |
|---|
| 49 |
int zoom = min(20, max(0, (int)round(log(sideLength/zoom0Length) / log(2)))); |
|---|
| 50 |
|
|---|
| 51 |
int cols = (int)pow(2,zoom); |
|---|
| 52 |
int rows = (int)pow(2,zoom); |
|---|
| 53 |
// println("rows/cols: " + rows + "/" + cols); |
|---|
| 54 |
// println("tileCount: " + (rows * cols)); |
|---|
| 55 |
|
|---|
| 56 |
// int screenCols = (int)ceil(cols * dist(0,0,width,height) / sideLength); |
|---|
| 57 |
// println("screenCols: " + screenCols); |
|---|
| 58 |
|
|---|
| 59 |
// find the biggest box the screen would fit in, aligned with the map: |
|---|
| 60 |
float screenMinX = 0; |
|---|
| 61 |
float screenMinY = 0; |
|---|
| 62 |
float screenMaxX = width; |
|---|
| 63 |
float screenMaxY = height; |
|---|
| 64 |
// println("screen: " + nf(screenMinX,1,3) + " " + nf(screenMinY,1,3) + " : " + nf(screenMaxX,1,3) + " " + nf(screenMaxY,1,3)); |
|---|
| 65 |
// TODO align this box! |
|---|
| 66 |
|
|---|
| 67 |
// find start and end columns |
|---|
| 68 |
int minCol = (int)floor(cols * (screenMinX-minX) / (maxX-minX)); |
|---|
| 69 |
int maxCol = (int)ceil(cols * (screenMaxX-minX) / (maxX-minX)); |
|---|
| 70 |
int minRow = (int)floor(rows * (screenMinY-minY) / (maxY-minY)); |
|---|
| 71 |
int maxRow = (int)ceil(rows * (screenMaxY-minY) / (maxY-minY)); |
|---|
| 72 |
// println("row/col: " + minCol + ", " + minRow + " : " + maxCol + ", " + maxRow); |
|---|
| 73 |
|
|---|
| 74 |
pushMatrix(); |
|---|
| 75 |
scale(1.0/pow(2,zoom)); |
|---|
| 76 |
for (int col = minCol; col <= maxCol; col++) { |
|---|
| 77 |
for (int row = minRow; row <= maxRow; row++) { |
|---|
| 78 |
fill(col >= 0 && col < cols && row >= 0 && row < rows ? 128 : 80); |
|---|
| 79 |
stroke(255); |
|---|
| 80 |
rect(col*256,row*256,256,256); |
|---|
| 81 |
fill(255); |
|---|
| 82 |
noStroke(); |
|---|
| 83 |
textFont(f,16); |
|---|
| 84 |
textAlign(LEFT, TOP); |
|---|
| 85 |
text("c:"+col+" "+"r:"+row+" "+"z:"+zoom, col*256, row*256); |
|---|
| 86 |
/* textAlign(RIGHT, TOP); |
|---|
| 87 |
text("c:"+col+" "+"r:"+row, (1+col)*256, row*256); |
|---|
| 88 |
textAlign(LEFT, BOTTOM); |
|---|
| 89 |
text("c:"+col+" "+"r:"+row, col*256, (1+row)*256); |
|---|
| 90 |
textAlign(RIGHT, BOTTOM); |
|---|
| 91 |
text("c:"+col+" "+"r:"+row, (1+col)*256, (1+row)*256); */ |
|---|
| 92 |
} |
|---|
| 93 |
} |
|---|
| 94 |
popMatrix(); |
|---|
| 95 |
|
|---|
| 96 |
popMatrix(); |
|---|
| 97 |
|
|---|
| 98 |
if (keyPressed) { |
|---|
| 99 |
if (key == CODED) { |
|---|
| 100 |
if (keyCode == LEFT) { |
|---|
| 101 |
a -= 1; |
|---|
| 102 |
} |
|---|
| 103 |
else if (keyCode == RIGHT) { |
|---|
| 104 |
a += 1; |
|---|
| 105 |
} |
|---|
| 106 |
} |
|---|
| 107 |
else if (key == '+' || key == '=') { |
|---|
| 108 |
sc *= 1.05; |
|---|
| 109 |
} |
|---|
| 110 |
else if (key == '_' || key == '-' && sc > 0.1) { |
|---|
| 111 |
sc *= 1.0/1.05; |
|---|
| 112 |
} |
|---|
| 113 |
else if (key == ' ') { |
|---|
| 114 |
sc = 1.0; |
|---|
| 115 |
tx = -128; |
|---|
| 116 |
ty = -128; |
|---|
| 117 |
a = 0; |
|---|
| 118 |
} |
|---|
| 119 |
} |
|---|
| 120 |
|
|---|
| 121 |
// println(); |
|---|
| 122 |
|
|---|
| 123 |
} |
|---|
| 124 |
|
|---|
| 125 |
void mouseDragged() { |
|---|
| 126 |
float dx = (mouseX - pmouseX) / sc; |
|---|
| 127 |
float dy = (mouseY - pmouseY) / sc; |
|---|
| 128 |
float angle = radians(-a); |
|---|
| 129 |
float rx = cos(angle)*dx - sin(angle)*dy; |
|---|
| 130 |
float ry = sin(angle)*dx + cos(angle)*dy; |
|---|
| 131 |
tx += rx; |
|---|
| 132 |
ty += ry; |
|---|
| 133 |
} |
|---|
| 134 |
|
|---|