Willkommen auf unserem Seminar-Blog

Immer auf dem aktuellen Stand bleiben

Dieser Seminar-Blog befindet sich noch im Aufbau und wird in den kommenden Tagen entsprechend verfeinert.

Member Login

Lost your password?

Registration is closed

Sorry, you are not allowed to register by yourself on this site!

You must either be invited by one of our team member or request an invitation by email at viad.info {at} zhdk {dot} ch.

GDB Aufgabe 05 – Interaktion

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.
To do
  • 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
Beim Rumexperimentieren entstandene Bilder:
/* --------------------------------------------------------------------------
 * 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