24. November 2011
Bei Aufgabe 05 im Kurs "Zeichenlehre" müssen wir die erstellten Permutationen und Raster interaktiv animieren. Ich habe in mein Programm folgende Funktionen eingebaut.- Mittels einer ArrayList werden die Zeichen dynamisch instanziert, damit diese einzeln manipuliert werden können
- Die Funktionen zum Zeichnen der Zeichen habe ich in eine Klasse umgewandelt
- Diverse Keyboardfunktionen
-
'i' to hide or display this panel
-
'w' and 'e' to switch forms"
-
'a' and 'd' to change distance between signs
-
'r' to reset distance to initial value
-
's' to save a screenshot", width/2, (height/2)+(height/20));
- Beim Wechseln zwischen den Zeichen und beim Ändern der Distanz gibt es einen Fade-Effekt. Dieser kann noch verstärkt werden, wenn man noLoop() im setup einsetzt.
- Am Anfang wird ein Infopanel angezeigt, welches die Funktionen erklärt. Es kann mit 'i' angezeigt oder ausgeschaltet werden.
- Must have
- Kinect-Funktion einbauen, um die Maus zu ersetzen
- Animationen optimieren
- Nice to have
- Mouse drag = die Bälle werden abgestossen vom Mousecursor und setzen sich in Bewegung
- Toggle Fade / no Fade
- Toggle Loop / No Loop
- Reset Funktion einbauen, um Elemente in Ausgangsposition zu versetzen
/* -------------------------------------------------------------------------- * Graphic Design Basics - Mouse Animation / Interaktion * -------------------------------------------------------------------------- * prog: Beni Achermann (based on Max Rheiner's examples 🙂 * date: 17/11/2011 * ---------------------------------------------------------------------------- */ // Importieren der Fullscreen-Library import fullscreen.*; // Initialisieren der HandCapture / simpleOpenNI Klasse HandCapture handCapture; boolean drawFlag=false; FullScreen fullScreen; ArrayList zeichen = new ArrayList(); // erstellen einer neuen ArrayList // PVector variables for the function that allows moving signs around PVector p1Move = new PVector(); PVector p2Move = new PVector(); // PVector variables for the animations caused by moving the cursor PVector p1 = new PVector(); PVector p2 = new PVector(); boolean drag = false; boolean infoPanel = true; int gridSize = 7; // 7*7 creates a grid of 49 signs int rand; int randInitial; int formNumber = 6; void setup() { size(1024,768); smooth(); rectMode(CENTER); ellipseMode(CENTER); frameRate(20); randInitial = 70; rand = randInitial; noCursor(); loop(); // interesting effects if turned off! // Populate the zeichen array for (int i=0; i<gridSize*gridSize;i++) { zeichen.add(new Zeichen(0, 0)); } fullScreen = new FullScreen(this); fullScreen.enter(); } // end of setup void draw() { float xStep; float yStep; xStep = (width - 2 * rand) / (float)(gridSize-1); yStep = (height - 2 * rand) / (float)(gridSize-1); // hintergrund loeschen //background(255); // ghosting pushStyle(); rectMode(CORNER); fill(0, 0, 0, 40); noStroke(); rect(0, 0, width, height); popStyle(); if (drag) { // zeichne die abschussrichtung pushStyle(); stroke(0, 255, 0); line(p1Move.x, p1Move.y, p2Move.x, p2Move.y); popStyle(); } // zeichne die Zeichen 🙂 pushMatrix(); translate(rand, rand); for (int i=0; i<gridSize;i++) { pushMatrix(); for (int j=0; j<gridSize;j++) { // // Start of stuff needed for cursor animation float adjustedMouseX = mouseX - width / 4; float adjustedMouseY = mouseY - height / 4; float posX = j * xStep+rand; float posY = i * yStep+rand; float distValueAdj = sqrt(sq((adjustedMouseX-posX))+sq((adjustedMouseY-posY))); float distValue = sqrt(sq((mouseX-posX))+sq((mouseY-posY))); p1.set (posX, posY, 0); p2.set (adjustedMouseX, adjustedMouseY, 0); PVector dir = PVector.sub(p2, p1); // end of stuff needed for cursor animation // // pushStyle(); // Platzhalter // rect(0,0,90,90); // Platzhalter // popStyle(); // Platzhalter Zeichen ball = (Zeichen) zeichen.get(j); // println(zeichen.get(j)); ball.draw(0, 0, distValue, distValueAdj); translate(xStep, 0.0f); } popMatrix(); translate(0.0f, yStep); } popMatrix(); displayInfoPanel(); } void mousePressed() { drag = true; p1Move.set(mouseX, mouseY, 0); p2Move.set(mouseX, mouseY, 0); } void mouseDragged() { p2Move.set(mouseX, mouseY, 0); } void displayInfoPanel() { if (infoPanel) { pushMatrix(); pushStyle(); // background / shadow (grey rectangle) fill(60); strokeJoin(ROUND); stroke(60); strokeWeight(12); rect(width/2+3, height/2+3, width/2, height/4); // foreground / background for text (white rectangle) fill(255); strokeJoin(ROUND); stroke(255); strokeWeight(12); rect(width/2, height/2, width/2, height/4); // infopanel text infoPanelText(width/2,height/2 - 30); // fill(0); // textAlign(CENTER); // text("'i' to hide or display this panel", width/2, (height/2)-(height/10)); // text("'w' and 'e' to switch forms", width/2, (height/2)-(height/20)); // text("'a' and 'd' to change distance between signs", width/2, (height/2)-(height/40)); // text("'r' to reset distance to initial value", width/2, (height/2)+(height)); // text("move the cursor to trigger animations", width/2, (height/2)+(height/10)); // text("'s' to save a screenshot", width/2, (height/2)+(height/20)); popMatrix(); popStyle(); } else { } } void infoPanelText(int textX, int textY) { String[] textInfo = { "'i' to hide or display this panel", "'w' and 'e' to switch forms", "'a' and 'd' to change distance between signs", "'r' to reset distance to initial value", "move the cursor to trigger animations", "'s' to save a screenshot" }; String superText = ""; for(int i = 0; i < textInfo.length; i++) { superText += textInfo[i]+"\r\n"; } fill(0); textAlign(CENTER); text(superText, textX, textY); } // end of infoPanelText void mouseReleased() { drag = false; // abschuss staerke berechnen PVector dir = PVector.sub(p2Move, p1Move); // laenge verkuerzen dir.mult(.09); // der ball wird neu ausgerichtet Zeichen temp = new Zeichen(100, 100); temp.set(p1Move, dir, .993); // zeichen.add(temp); } // KEYBOARD FUNCTIONS void keyPressed() { switch(key) { case 's': saveFrame("screenshot-####.png"); // Speichern eines Screenshots auf Druck von S println("Saved screenshot-##.png"); redraw(); break; case 'd': rand+=40; if (rand > 400) { // If rand ist bigger than 400 rand = randInitial; //...set it back to 10 } println("Increased distance from rand to " + rand); redraw(); break; case 'a': rand-=40; if (rand < randInitial) { // If rand ist smaller than 10 rand = 400; //...set it back to 400 } println("Increased rand to " + rand); redraw(); break; case 'w': formNumber++; if (formNumber > 7) { // If formNumber ist bigger than 6 formNumber = 1; //...set it back to 1 } println("Form: " + formNumber); redraw(); break; case 'e': formNumber--; if (formNumber < 1) { // If formNumber is smaller than 1 formNumber = 6; //...set it back to 6 } println("Form: " + formNumber); redraw(); break; case 'i': if (infoPanel) { infoPanel = false; println("Hiding information screen"); } else { infoPanel = true; println("Displaying information screen"); } redraw(); break; case 'r': rand = randInitial; redraw(); break; } }
import SimpleOpenNI.*; class HandCapture { SimpleOpenNI _context; boolean _drawFlag=false; PVector _handVec = new PVector(); String _lastGesture = ""; PVector _screenPos = new PVector(); PApplet _parent; boolean _handsTrackFlag = false; HandCapture(PApplet parent) { _parent = parent; _context = new SimpleOpenNI(_parent); // mirror is by default enabled _context.setMirror(true); // enable depthMap _context.enableDepth(); // enable camera _context.enableRGB(); _context.enableHands(); _context.enableGesture(); _context.addGesture("RaiseHand"); // align depth data to image data _context.alternativeViewPointDepthToImage(); } boolean isHandTracked() { return _handsTrackFlag; } PVector handPos() { return _screenPos; } PVector handPos3d() { return _handVec; } PImage depthImage() { return _context.depthImage(); } PImage rgbImage() { return _context.rgbImage(); } int width() { return _context.depthWidth(); } int height() { return _context.depthHeight(); } void update() { _context.update(); _context.convertRealWorldToProjective(_handVec,_screenPos); } void onCreateHands(int handId, PVector pos, float time) { _handsTrackFlag = true; _handVec = pos; } void onUpdateHands(int handId, PVector pos, float time) { _handVec = pos; } void onDestroyHands(int handId, float time) { _handsTrackFlag = false; _context.addGesture(_lastGesture); } void onRecognizeGesture(String strGesture, PVector idPosition, PVector endPosition) { _lastGesture = strGesture; _context.removeGesture(strGesture); _context.startTrackingHands(endPosition); } void onProgressGesture(String strGesture, PVector position, float progress) { } }
/* -------------------------------------------------------------------------- * Zeichenklasse * -------------------------------------------------------------------------- * prog: Beni Achermann * date: 24/11/2011 * ---------------------------------------------------------------------------- */ class Zeichen { PVector _pos; PVector _dir; float _dampV; int _w; int _h; int formSize = 90; float dist; float distValueGlobal; float distValueAdjGlobal; float scaler; // konstruktor Zeichen(int x, int y) { _pos = new PVector(width/2, height/2); _dir = new PVector(0,0); _dampV = 1; } // setzt die neue pos + richtung + daempfung void set(PVector pos,PVector dir,float dampV) { _pos = pos.get(); _dir.add(dir); _dampV = dampV; } // erneuert die aktuelle position void calcPos() { // aktuelle position verschieben _pos.add(_dir); // bewegungs vektor veraendert _dir.mult(_dampV); // teste horizontal if(_pos.x + _w/2 > width) { _dir.x *= -1; _pos.x = width - _w/2; } else if(_pos.x - _w/2 < 0) { _dir.x *= -1; _pos.x = _w/2; } // teste vertikal if(_pos.y + _h/2 > height) { _dir.y *= -1; _pos.y = height - _w/2; } else if(_pos.y - _h/2 < 0) { _dir.y *= -1; _pos.y = _h/2; } } // zeichnet die Zeichen void draw(int x, int y, float _distValue, float _distValueAdj) { distValueGlobal = _distValue; distValueAdjGlobal = _distValueAdj; calcPos(); switchingZeichen(x,y); } // CODE FOR CONSTRUCTING THE BASIC FORMS void switchingZeichen(float x, float y) { if(formNumber == 1) { drawSign1(x, y); } if(formNumber == 2) { drawSign2(x, y); } if(formNumber == 3) { pushMatrix(); drawSign3(x, y); popMatrix(); } if(formNumber == 4) { drawSign4(x, y); } if(formNumber == 5) { drawSign5(x, y); } if(formNumber == 6) { drawSign6(x, y); } if(formNumber == 7) { drawSign7(x, y); } } void drawSign1(float x, float y) { // white ellipse & with smaller black one in it, innit. dist = map(distValueGlobal, 0, width * 1.41, 0, 100); // mouse animation scaler = map(distValueGlobal, 0, width*1.41, 0, 1.5); // mouse animation pushMatrix(); scale(scaler); // mouse animation pushStyle(); fill(255); ellipse(0, 0, formSize, formSize); fill(0); noStroke(); ellipse(0, 0, formSize/3, formSize/3); popStyle(); popMatrix(); } void drawSign2(float x, float y) { // the symbol from aufgabe 04 circleFilledWhiteOutlineBlack(x, y, 1.0, 0.0, 4); circleFilledBlack(x+formSize/2, y, 1.0, 0.0, 0); circleFilledBlack(x, y, 0.5, 0.0, 0); circleFilledWhite(x+7, y, 0.5, 0.0, 0); } void drawSign3(float x, float y) { //very small ellipses (dots) in a grid //rect(x,y,formSize,formSize); dist = map(distValueGlobal, 0, width * 3, 3, 100); for (int i = 1; i < 9; i++) { pushMatrix(); for (int j = 1; j < 9; j++) { pushStyle(); fill(255); noStroke(); ellipse(0-30, 0-30, 4, 4); popStyle(); scale(dist/3); } popMatrix(); translate(10,10); } } void drawSign4(float x, float y) { // ellipse with outline dist = map(distValueGlobal, 0, width * 1.41, 0, 100); pushStyle(); stroke(2); fill(255); ellipse(x, y, dist, formSize); ellipse(x, y, dist/2, formSize/2); popStyle(); } void drawSign5(float x, float y) { // lineament dist = map(distValueGlobal, 0, width * 1.41, 0, 15); pushMatrix(); for (int i = 1; i <= 9; i++) { // lines pushStyle(); stroke(255); strokeWeight(1); line(0, 0, formSize, 0); translate(0, dist); popStyle(); } popMatrix(); } void drawSign6(float x, float y) { // geknicktes Lineament // map nimmt den eingehenden Wert (distValueGlobal), welcher sich in einem Range zwischen // 0 und der Weite des Dokuments befindet. // Dieser Wert wird dann in den Range zwischen 0 und 100 umgerechnet. dist = map(distValueGlobal, 0, width, 0, 100); pushMatrix(); for (int i = 1; i <= 9; i++) { pushStyle(); stroke(255); strokeWeight(1); line(0, 0, dist, dist); line(dist, dist, formSize, 0); translate(0, 10); popStyle(); } popMatrix(); } void drawSign7(float x, float y) { //very small ellipses (dots) in a grid //rect(x,y,formSize,formSize); dist = map(distValueGlobal, 0, width * 3, 1, 10); for (int i = 1; i < 9; i++) { pushMatrix(); for (int j = 1; j < 9; j++) { pushStyle(); fill(255); noStroke(); ellipse(0, 0, 2, 2); popStyle(); translate(0,dist); } popMatrix(); translate(dist,0); } } void circleFilledWhite (float translateX, float translateY, float scaleValue, float rotateValue, int strokeWeightValue) { dist = map(distValueGlobal, 0, width * 1.41, 0, 100); pushMatrix(); translate(translateX, translateY); scale(scaleValue); rotate(rotateValue); noStroke(); fill(255); ellipse(0, 0, dist, dist); popMatrix(); } void circleFilledWhiteOutlineBlack(float translateX, float translateY, float scaleValue, float rotateValue, int strokeWeightValue) { pushMatrix(); translate(translateX, translateY); scale(scaleValue); rotate(rotateValue); fill(0); strokeWeight(strokeWeightValue); fill(255); ellipse(0, 0, formSize, formSize); popMatrix(); } void circleFilledBlack (float translateX, float translateY, float scaleValue, float rotateValue, int strokeWeightValue) { pushMatrix(); translate(translateX, translateY); scale(scaleValue); rotate(rotateValue); fill(0); noStroke(); ellipse(0, 0, formSize, formSize); popMatrix(); } } // end of class