Distorting a Classic
You can use your face to turn a classical sculpture into a glitching digital artifact, eyebrow height is correlated with noise on the surface and mouth openness is correlated with twisting the sculpture.
This has been a long process. The end product resulted in a modification of my original idea, which was to be able to manipulate specific parts of the face, but I couldn’t grab only a specific section of pixels to distort, since it was an imported object. If I had made the head in processing using 3d objects I would have been able to. I used Hemesh to distort the head and toxiclibs to import the stl file into processing. The head is a model of Memory by Daniel Chester French, it is found in the Metropolitan
code:
//Charlotte Stiles
//Thank you Matthew Plummer-Fernandez for the code to import stl to hemesh using toxiclibs http://www.plummerfernandez.com/
//bend and noise code from Hemesh library http://hemesh.wblut.com/
//head is from scotta3d on thingsverse http://www.thingiverse.com/thing:24335
//the head is a model of Memory by Daniel Chester French, it is found in the Metropolitan
import wblut.math.*;
import wblut.processing.*;
import wblut.core.*;
import wblut.*;
import wblut.hemesh.*;
import wblut.geom.*;
// Toxiclibs for the import stl and save color stl
import toxi.geom.*;
import toxi.geom.mesh.*;
import toxi.math.*;
import toxi.processing.*;
import oscP5.*;
OscP5 oscP5;
//pshape is for importing my stl
PShape s;
PVector posePosition;
boolean found;
float eyeLeftHeight;
float eyeRightHeight;
float mouthHeight;
float mouthWidth;
float leftEyebrowHeight;
float rightEyebrowHeight;
float MN; //eyebrow to eye
float poseScale;
String stlFilename = "memory_head.stl";
//this is for noise and everything else vv
HE_Mesh mesh, copymesh;
WB_Render render;
//this is for bend vv
WB_Plane P;
WB_Line L;
HEM_Bend bendModifier;
WB_GeometryFactory gf=WB_GeometryFactory.instance();
void setup() {
size(800, 800, P3D);
createMesh();
HEM_Noise modifier=new HEM_Noise();
modifier.setDistance(20);
copymesh.modify(modifier);
//for noise^^
bendModifier=new HEM_Bend();
P=new WB_Plane(0,0,-200,0,0,1);
bendModifier.setGroundPlane(P);// Ground plane of bend modifier
L=new WB_Line(0,0,-200,-1,0,-200);
bendModifier.setBendAxis(L);// Bending axis
bendModifier.setAngleFactor(30.0/400);// Angle per unit distance (in degrees) to the ground plane
// bend axis by an angle d*angleFactor;
bendModifier.setPosOnly(false);// apply modifier only on positive side of the ground plane?
mesh.modify(bendModifier);
render=new WB_Render(this);
oscP5 = new OscP5(this, 8338);
oscP5.plug(this, "mouthWidthReceived", "/gesture/mouth/width");
oscP5.plug(this, "mouthHeightReceived", "/gesture/mouth/height");
oscP5.plug(this, "eyebrowLeftReceived", "/gesture/eyebrow/left");
oscP5.plug(this, "eyebrowRightReceived", "/gesture/eyebrow/right");
oscP5.plug(this, "eyeLeftReceived", "/gesture/eye/left");
oscP5.plug(this, "eyeRightReceived", "/gesture/eye/right");
oscP5.plug(this, "jawReceived", "/gesture/jaw");
oscP5.plug(this, "nostrilsReceived", "/gesture/nostrils");
oscP5.plug(this, "found", "/found");
oscP5.plug(this, "poseOrientation", "/pose/orientation");
oscP5.plug(this, "posePosition", "/pose/position");
oscP5.plug(this, "poseScale", "/pose/scale");
}
void draw() {
background(230);
directionalLight(255, 255, 255, 1, 1, -1);
directionalLight(127, 127, 127, -1, -1, 1);
if (found) {
translate(posePosition.x, posePosition.y+300);
scale(poseScale*2);
}
rotateY(400*1.0/width*TWO_PI);
rotateX(200*1.0/height*TWO_PI);
HEM_Noise modifier=new HEM_Noise();
copymesh=mesh.get();
MN = rightEyebrowHeight - eyeRightHeight - 4;
// println(MN);
if (MN < 0) MN=0; //eyebrow eye ratio make sure it doesnt go into negative
modifier.setDistance(MN/2);
copymesh.modify(modifier);
float heightWidthRatio=mouthHeight/mouthWidth;
println(heightWidthRatio);
if (heightWidthRatio < .2) heightWidthRatio= 0;
L=gf.createLineThroughPoints(0,0, heightWidthRatio-100,-1,0,heightWidthRatio-100);
//this one controls the speed vv
bendModifier.setAngleFactor(20* 0.030 *heightWidthRatio);
bendModifier.setBendAxis(L);
mesh.modify(bendModifier);
noStroke();
render.drawEdges(mesh);
noStroke();
render.drawFaces(copymesh);
}
public void mouthWidthReceived(float w) {
// println("mouth Width: " + w);
mouthWidth = w;
}
public void mouthHeightReceived(float h) {
// println("mouth height: " + h);
mouthHeight = h;
}
public void eyebrowRightReceived(float h) {
// println("eyebrow right: " + h);
rightEyebrowHeight = h;
}
public void eyeRightReceived(float h) {
// println("eye right: " + h);
eyeRightHeight = h;
}
public void found(int i) {
//println("found: " + i); // 1 == found, 0 == not found
found = i == 1;
}
public void posePosition(float x, float y) {
// println("pose position\tX: " + x + " Y: " + y );
posePosition = new PVector(x, y);
}
public void poseScale(float s) {
// println("scale: " + s);
poseScale = s;
}
public void poseOrientation(float x, float y, float z) {
// println("pose orientation\tX: " + x + " Y: " + y + " Z: " + z);
}
void oscEvent(OscMessage theOscMessage) {
if (theOscMessage.isPlugged()==false) {
// println("UNPLUGGED: " + theOscMessage);
}
}
void createMesh(){
mesh = new HE_Mesh(fromStl(stlFilename));
copymesh= mesh.get();
}
HEC_FromFacelist fromStl(String stlName) {
println("Start Build");
WETriangleMesh wemesh = (WETriangleMesh) new STLReader().loadBinary(sketchPath(stlName), STLReader.WEMESH);
//convert toxi mesh to a hemesh. Thanks to wblut
int n=wemesh.getVertices().size();
ArrayList points= new ArrayList(n);
for (Vec3D v : wemesh.getVertices ()) {
points.add(new WB_Point(v.x, v.y, v.z));
}
int[] toxiFaces=wemesh.getFacesAsArray();
int nf=toxiFaces.length/3;
int[][] faces=new int[nf][3];
for (int i=0; i