Xastol – FaceOSC
For the FaceOSC project, I decided to grow off of my plotting project (./xastol/09/29/xastol-plot/). I decided to develop the characters I generated in the plotting project as “wear-able” identities.
Every face is randomly generated and changes when the user presses the UP key. In terms of the characters in relation to the user’s face, they basically follow all movements made by the head (rotation and translation among all axises: x, y, z). Additionally, the mouth moves in relation to the user’s mouth (height and width) and the eyes change size based off of eyebrow movement: this was initially going to be in relation to the actual eye-openness of the user, however, I noticed I got a better effect while tracking the eyebrow position.
Random Face Generation Demo
Random Face Generation (Sound of Silence Performance)
My main goal for this project was to expand upon previous work and find new/interesting ways of presenting a concept. I felt this project was important and realizing these new ideas. In the overall scheme of things, I think I achieved my goal fairly well. However, I’m not sure if I did well in terms of maintaining the originality of the initial concept (from the plotting project). I was having a hard time deciding to strictly maintain the initial concept or use it as a catalyst and then shoot for the development of an entirely new way of presenting the initial idea. In the end, I came up with a project that is still very close to the initial idea (i.e. – generative faces, face shapes, sizes, etc.) but also has some detail changes (i.e. – new colors, slight differences in shape movement, etc.).
CODE
//
// 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
//
//Xavier Apostol
//Generative Faces: Plotter Project Concept
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;
float sz = 1;
float spacing = 100;
float genSz = spacing/4;
float fcOff = genSz/2;
//Initialization of Colors
float R = random(255);
float G = random(255);
float B = random(255);
//Initialization of Head
float rotInt = 15;
float hdX = cos(sz) + random(genSz, 3*genSz);
float hdY = sin(sz) + random(genSz, 3*genSz);
float rotAngle = random(-rotInt,rotInt);
//Initialization of Eyes
float lEyeX1 = sin(sz*0) + random(genSz);
float lEyeY1 = cos(sz*0) + random(genSz);
float rEyeX1 = sin(sz*0) + random(genSz);
float rEyeY1 = cos(sz*0) + random(genSz);
float lEyeX2 = sin(sz*1) + random(genSz);
float lEyeY2 = cos(sz*1) + random(genSz);
float rEyeX2 = sin(sz*1) + random(genSz);
float rEyeY2 = cos(sz*1) + random(genSz);
float ranREye = random(7, 9);
float ranLEye = random(7, 9);
//Initialization of Mouth
float mthX = cos(sz) + random(genSz);
float mthY = sin(sz) + random(genSz);
float ranM = random(-0.1, 1.5);
//Initialization of Spine
float hdOffset = hdY/1.5;
float spineSz = random(genSz/2);
float spXOff1 = random(-8, 8);
float spYOff1 = hdOffset + random(genSz/3);
float spXOff2 = random(-8, 8)+spXOff1;
float spYOff2 = random(genSz/3)+spYOff1;
float spXOff3 = random(-8, 8)+spXOff2;
float spYOff3 = random(genSz/3)+spYOff2;
float spXOff4 = random(-8, 8)+spXOff3;
float spYOff4 = random(genSz/3)+spYOff3;
float spXOff5 = random(-8, 8)+spXOff4;
float spYOff5 = random(genSz/3)+spYOff4;
void setup() {
size(800, 600, OPENGL);
frameRate(30);
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");
}
void keyPressed() {
if (key == CODED) {
if (keyCode == UP) {
//Create an entirely new character.
//For Eyes
lEyeX1 = sin(sz*0) + random(genSz);
lEyeY1 = cos(sz*0) + random(genSz);
rEyeX1 = sin(sz*0) + random(genSz);
rEyeY1 = cos(sz*0) + random(genSz);
lEyeX2 = sin(sz*1) + random(genSz);
lEyeY2 = cos(sz*1) + random(genSz);
rEyeX2 = sin(sz*1) + random(genSz);
rEyeY2 = cos(sz*1) + random(genSz);
ranREye = random(7, 9);
ranLEye = random(7, 9);
//For Mouth
mthX = cos(sz) + random(genSz);
mthY = sin(sz) + random(genSz);
ranM = random(-0.1, 1.5);
//For Spine
spineSz = random(genSz/2);
spXOff1 = random(-8, 8);
spYOff1 = hdOffset + random(genSz/3);
spXOff2 = random(-8, 8) + spXOff1;
spYOff2 = random(genSz/3) + spYOff1;
spXOff3 = random(-8, 8) + spXOff2;
spYOff3 = random(genSz/3) + spYOff2;
spXOff4 = random(-8, 8) + spXOff3;
spYOff4 = random(genSz/3) + spYOff3;
spXOff5 = random(-8, 8) + spXOff4;
spYOff5 = random(genSz/3) + spYOff4;
//For Head
hdX = cos(sz) + random(genSz, 3*genSz);
hdY = sin(sz) + random(genSz, 3*genSz);
rotAngle = random(-rotInt,rotInt);
//For Colors
R = random(255);
G = random(255);
B = random(255);
draw();
}
}
}
void draw() {
background(0);
strokeWeight(1);
noFill();
if(found != 0) {
pushMatrix();
translate(posePosition.x, posePosition.y);
//Scales head and allows for rotations
scale(poseScale*2);
rotateY(0 - poseOrientation.y);
rotateX(0 - poseOrientation.x);
rotateZ(poseOrientation.z);
rotate(radians(rotAngle));
ellipse(0,0, hdX,hdY);
popMatrix();
//FACE
translate(posePosition.x, posePosition.y);
scale(poseScale);
noFill();
//Eyes
float eyeFac = 1;
float eyeBL = eyebrowLeft * 2;
float eyeBR = eyebrowRight * 2;
ellipse(-20,eyeLeft * -ranLEye, lEyeX1*eyeFac + eyeBL,lEyeY1*eyeFac + eyeBL);
ellipse(20,eyeRight * -ranREye, rEyeX1*eyeFac + eyeBR,rEyeY1*eyeFac + eyeBR);
ellipse(-20,eyeLeft * -ranLEye, lEyeX2*eyeFac + eyeBL,lEyeY2*eyeFac + eyeBL);
ellipse(20,eyeRight * -ranREye, rEyeX2*eyeFac + eyeBR,rEyeY2*eyeFac + eyeBR);
//Mouth
ellipse(0, 20*ranM, mouthWidth* mthX/3, mouthHeight * mthY);
//BODY/BUBBLES
stroke(R,G,B);
ellipse(spXOff1,spYOff1, spineSz,spineSz);
ellipse(spXOff2,spYOff2, spineSz,spineSz);
ellipse(spXOff3,spYOff3, spineSz,spineSz);
ellipse(spXOff4,spYOff4, spineSz,spineSz);
ellipse(spXOff5,spYOff5, spineSz,spineSz);
}
}
// 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);
}
}