Ticha-Como se llama

Initially, I wanted to create a full-bodied, trippy-looking, fantastical creature whose motions reacted to the user’s facial expressions. I researched different character designs found on Pictoplasma and deviantART, but mostly drew inspiration from the Faun in Guillermo del Toro’s Pan’s Labyrinth. The Faun was a particularly interesting subject for me because not only was its design a well-crafted fusion of plant and animal, but also its movements and gestures strongly complemented its plantlike characteristics. My ‘final’ creature design, with its wooden ram horns, frog body, bushy hair, human hands, and venus flytrap for a tail, was inspired by the Faun and a bizarre legendary creature called the chimera.

Soon I realized that I was getting too entangled in the design and aesthetics that I did not give much thought into how the creature would move, or how it would interact with its environment. When I was unable to formulate an algorithm that would allow it to walk in a convincing manner, I decided to scrap my ram-frog-tree-bush-human-flytrap creature entirely and go with something more simple.

The ‘final‘ final creature design is a slightly cuter, llama-esque creature (because as I was painting it on Tuesday Jun noted that it resembled a llama). Its movements are controlled by the eyebrows, mouth, and head rotation – though I wanted it to be affected by the head tilt as well but ran into technical difficulties. I am more or less satisfied with the result, and found the extra ladybug feature to be an effective way to get the user more engaged with the character. If I had more time, I would make the ladybug fly more convincingly and try to work out the technical issues I had with the head tilting.

// a template for receiving face tracking osc messages from
// Kyle McDonald's FaceOSC https://github.com/kylemcdonald/ofxFaceTracker
//
// 2012 Dan Wilcox danomatika.com
// for the IACD Spring 2012 class at the CMU School of Art
//
// adapted from from Greg Borenstein's 2011 example
// http://www.gregborenstein.com/
// https://gist.github.com/1603230
//
import oscP5.*;
OscP5 oscP5;

// num faces found
int found;

// pose
float poseScale;
PVector posePosition = new PVector();
PVector poseOrientation = new PVector();

// gesture
float mouthHeight;
float mouthWidth;
float eyeLeft;
float eyeRight;
float eyebrowLeft;
float eyebrowRight;
float jaw;
float nostrils;

//fetus
PImage face;
PImage body;
PImage lefteye;
PImage righteye;
PImage leftlid;
PImage rightlid;
PImage upperlip;
PImage llamajaw;
PImage ladybug;
PImage flyinglady;

int x = 0;

boolean moving = false;
boolean flying = true;

Ladybug myLadybug;

void setup() {
  size(600, 525);

  face = loadImage("face.png");
  body = loadImage("body.png");
  lefteye = loadImage("left eye.png");
  righteye = loadImage("right eye.png");
  leftlid = loadImage("left lid.png");
  rightlid = loadImage("right lid.png");
  upperlip = loadImage("mouth top.png");
  llamajaw = loadImage("mouth bottom.png");
  ladybug = loadImage("ladybug.png");
  flyinglady = loadImage("ladybug-flying.png");

  oscP5 = new OscP5(this, 8338);
  oscP5.plug(this, "found", "/found");
  oscP5.plug(this, "poseScale", "/pose/scale");
  oscP5.plug(this, "posePosition", "/pose/position");
  oscP5.plug(this, "poseOrientation", "/pose/orientation");
  oscP5.plug(this, "mouthWidthReceived", "/gesture/mouth/width");
  oscP5.plug(this, "mouthHeightReceived", "/gesture/mouth/height");
  oscP5.plug(this, "eyeLeftReceived", "/gesture/eye/left");
  oscP5.plug(this, "eyeRightReceived", "/gesture/eye/right");
  oscP5.plug(this, "eyebrowLeftReceived", "/gesture/eyebrow/left");
  oscP5.plug(this, "eyebrowRightReceived", "/gesture/eyebrow/right");
  oscP5.plug(this, "jawReceived", "/gesture/jaw");
  oscP5.plug(this, "nostrilsReceived", "/gesture/nostrils");

  myLadybug = new Ladybug();

  noStroke();
  fill(0);
}

void draw() {  
  background(255);

  //I tried to allow the character to tilt its head
  //but due to high memory usage Processing just decided not to work. :/
  //translate(314,514);
  //rotate(poseOrientation.z);

  if (found > 0) {
    //pushMatrix();
    //translate(-314,-514);

    image(lefteye, 0, 0);
    image(righteye, 0, 0);

    float eyeDir = map(poseOrientation.y, -0.16, 0.04, -5, 5);
    ellipse(238+eyeDir, 337, 30, 30);
    ellipse(371+eyeDir, 337, 30, 30);

    /* for whatever reason, the eyebrow tracking is much more 
     appropriate for blink motions.... */
    float blinkleft = map(eyebrowLeft, 7.3, 8.350, -5, 45);
    float blinkright = map(eyebrowRight, 7.3, 8.350, -5, 45);

    image(leftlid, 0, blinkleft);
    image(rightlid, 0, blinkright);

    image(face, 0, 0);
    image(body, 0, 0);

    float mouthopen = map(mouthHeight, 1.0, 7.0, 0, 30);

    moving = mouthopen > 4.1;

    image(llamajaw, 0, mouthopen);

    image(upperlip, 0, 0);

    //popMatrix();
  }

  myLadybug.fly();
  myLadybug.display();
}

// OSC CALLBACK FUNCTIONS

public void found(int i) {
  println("found: " + i);
  found = i;
}

public void poseScale(float s) {
  println("scale: " + s);
  poseScale = s;
}

public void posePosition(float x, float y) {
  println("pose position\tX: " + x + " Y: " + y );
  posePosition.set(x, y, 0);
}

public void poseOrientation(float x, float y, float z) {
  println("pose orientation\tX: " + x + " Y: " + y + " Z: " + z);
  poseOrientation.set(x, y, z);
}

public void mouthWidthReceived(float w) {
  println("mouth Width: " + w);
  mouthWidth = w;
}

public void mouthHeightReceived(float h) {
  println("mouth height: " + h);
  mouthHeight = h;
}

public void eyeLeftReceived(float f) {
  println("eye left: " + f);
  eyeLeft = f;
}

public void eyeRightReceived(float f) {
  println("eye right: " + f);
  eyeRight = f;
}

public void eyebrowLeftReceived(float f) {
  println("eyebrow left: " + f);
  eyebrowLeft = f;
}

public void eyebrowRightReceived(float f) {
  println("eyebrow right: " + f);
  eyebrowRight = f;
}

public void jawReceived(float f) {
  println("jaw: " + f);
  jaw = f;
}

public void nostrilsReceived(float f) {
  println("nostrils: " + f);
  nostrils = f;
}

// all other OSC messages end up here
void oscEvent(OscMessage m) {
  if (m.isPlugged() == false) {
    println("UNPLUGGED: " + m);
  }
}

class Ladybug {
  float posX;
  float posY;
  float spdX;
  float spdY;

  Ladybug() {
    posX = random(40, 400);
    posY = random(60, 400);
    spdX = random(-2, 2);
    spdY = random(-2, 2);
  }

  void fly() {
    if (!moving && 264 < = posX && posX <= 303 
      && 300 <= posY && posY <= 342) {
      flying = false;
      spdX = 0;
      spdY = 0;
    }

    else {
      if (spdX == 0) {
        //it'll move away from the mouth
        spdX = random(-2, 2);
        spdY = random(-3, 0);
      }

      posX += spdX;
      posY += spdY;
      flying = true;

      if (posX < 40 || posX > 400) {
        spdX *= -1;
      }

      if (posY < 60 || posY > 400) {
        spdY *= -1;
      }
    }
  }

  void display() {

    if (flying) {
      image(flyinglady, posX, posY);
    }

    else {
      image(ladybug, posX, posY);
    }
  }
} 

< \pre>

Comments are closed.