//import moviemaker.*; import processing.opengl.*; /** * Warp Mesh * * So the whole point of this application is to allow a user to define a warp * between to different faces. Whoo. */ //MovieMaker mm; //public boolean bMakeMovie = false; public final int NORMAL_SMOOTH_PASSES = 50; public final int FAST_SMOOTH_PASSES = 500; public final int MESH_SIZE = 34; public final int MESH_SELECT_RADIUS = 4; public final float TIME_STEP = 0.008; public float TEXT_Y; public float TEXT_X_START; public float TEXT_X_MIDDLE; public float TEXT_X_END; public float PIC_Y; public float PIC_X; public float PIC_X_END; public final String HINT1 = "Click and drag on the image to deform it. Click here when done."; public final String HINT2 = "Please correlate the faces. Click here when done."; public final String HINT3 = "Cofirm correlation and tweak as needed. Click here when done."; public final String HINT4 = "Click and drag to deform the last face. Click here when done."; // all the states public static String STATE_LOADING = "loading state"; public static String STATE_WARP_FIRST = "first warp state"; public static String STATE_WARP_LAST = "last warp state"; public static String STATE_WARP_BLEND_DOTS = "correlating step"; public static String STATE_WARP_BLEND_TWEAK = "tweak the blend step"; public static String STATE_PRE_ANIMATION = "pre animation wait"; public static String STATE_ANIM_FIRST = "animating the first part"; public static String STATE_ANIM_BLEND = "animating the blend"; public static String STATE_ANIM_LAST = "animating the last"; public static String STATE_ANIM_DONE = "All done!"; String state; // timers float textTimer; // all the other stuff PFont slideFont; PImage first; PImage last; Correlator correlator; QuadMesh firstMesh; QuadMesh lastMesh; QuadMesh firstBlendMesh; QuadMesh lastBlendMesh; FaceWarp firstWarp; FaceWarp lastWarp; FaceWarp firstBlendWarp; FaceWarp lastBlendWarp; FaceBlend faceBlend; SlideText newText; SlideText oldText; //// // setup //// void setup(){ //this.last = loadImage("postal.png"); //this.first = loadImage("devin2.png"); this.last = loadImage("postal.png"); this.first = loadImage("devin2.png"); this.slideFont = loadFont("slideFont.vlw"); TEXT_Y = height - 12; TEXT_X_START = width; TEXT_X_MIDDLE = 12; TEXT_X_END = -width; PIC_X = (width / 2) - (this.last.width / 2); PIC_X_END = -this.last.width - 100; PIC_Y = (height / 2) - (this.last.height / 2); frameRate(30); this.state = STATE_LOADING; //size(this.last.width * 3, this.last.height + 200, OPENGL); size(700, 400, P3D); //this.mm = new MovieMaker(this, width, height, "facewarp.mov", MovieMaker.JPEG, MovieMaker.HIGH, 30); } void loadAssets(){ correlator = new Correlator(); firstMesh = new QuadMesh(this.first, MESH_SIZE); lastMesh = new QuadMesh(this.last, MESH_SIZE); firstBlendMesh = new QuadMesh(this.first, MESH_SIZE); lastBlendMesh = new QuadMesh(this.last, MESH_SIZE); firstWarp = new FaceWarp(firstMesh); lastWarp = new FaceWarp(lastMesh); firstBlendWarp = new FaceWarp(firstBlendMesh); lastBlendWarp = new FaceWarp(lastBlendMesh); // the face blend is going to need seperate ones // to fool with, so, lets make new ones! faceBlend = new FaceBlend(firstBlendWarp, lastBlendWarp); } //// // draw //// void draw(){ background(color(255)); if(this.state == STATE_LOADING){ this.loadAssets(); this.state = STATE_WARP_FIRST; //set the text this.newText = new SlideText(HINT1, this.slideFont, new Point(TEXT_X_START, TEXT_Y)); this.newText.setFinalPoint(new Point(TEXT_X_MIDDLE, TEXT_Y)); //set the image states this.firstMesh.setCurrentDrawPoint(new Point(width, PIC_Y)); this.firstMesh.setFinalDrawPoint(new Point(PIC_X, PIC_Y)); } else if(this.state == STATE_WARP_FIRST){ this.firstWarp.tick(TIME_STEP); this.firstWarp.draw(); this.newText.draw(); } else if(this.state == STATE_WARP_LAST){ // old stuff this.oldText.draw(); this.faceBlend.tick(TIME_STEP); this.faceBlend.draw(); // new stuff this.newText.draw(); this.lastWarp.tick(TIME_STEP); this.lastWarp.draw(); } else if(this.state == STATE_WARP_BLEND_DOTS){ // the old stuff this.firstWarp.tick(TIME_STEP); this.firstWarp.draw(); this.oldText.draw(); // the new stuff this.newText.draw(); this.faceBlend.draw(); this.faceBlend.tick(TIME_STEP); this.correlator.draw(); } else if(this.state == STATE_WARP_BLEND_TWEAK){ // the old stuff this.oldText.draw(); // the new stuff this.newText.draw(); this.faceBlend.tick(TIME_STEP); this.faceBlend.draw(); } else if(this.state == STATE_PRE_ANIMATION){ this.textTimer += TIME_STEP; this.oldText.draw(); this.newText.draw(); if(this.textTimer > .5){ // snap to the animation state this.state = STATE_ANIM_FIRST; // set up the constraint positions for all the meshes this.firstMesh.setCurrentDrawPoint(new Point(PIC_X, PIC_Y)); this.firstMesh.setFinalDrawPoint(new Point(PIC_X, PIC_Y)); this.firstMesh.hideContraints(); this.firstWarp.setPlayhead(0); this.lastMesh.setCurrentDrawPoint(new Point(PIC_X, PIC_Y)); this.lastMesh.setFinalDrawPoint(new Point(PIC_X, PIC_Y)); this.lastMesh.hideContraints(); this.lastWarp.setPlayhead(0); this.firstBlendMesh.setCurrentDrawPoint(new Point(PIC_X, PIC_Y)); this.firstBlendMesh.setFinalDrawPoint(new Point(PIC_X, PIC_Y)); this.firstBlendMesh.hideContraints(); this.lastBlendMesh.setCurrentDrawPoint(new Point(PIC_X, PIC_Y)); this.lastBlendMesh.setFinalDrawPoint(new Point(PIC_X, PIC_Y)); this.lastBlendMesh.hideContraints(); this.faceBlend.setPlayhead(0); //start is up! this.firstWarp.start(); } } else if(this.state == STATE_ANIM_FIRST){ this.firstWarp.tick(TIME_STEP); this.firstWarp.draw(); if(! this.firstWarp.isAnimating()){ // done! next one! this.state = STATE_ANIM_BLEND; this.faceBlend.start(); //copy over the final -> initial constraints int meshSize = this.firstMesh.meshSize; Point[][] fPoints = this.firstMesh.getMesh(); Point[][] iPoints = this.firstBlendMesh.getMesh(); for(int x = 0; x <= meshSize; x ++){ for(int y = 0; y <= meshSize; y ++){ iPoints[x][y].setTo(fPoints[x][y]); } } } } else if(this.state == STATE_ANIM_BLEND){ this.faceBlend.tick(TIME_STEP); this.faceBlend.draw(); if(! this.faceBlend.isAnimating()){ // done! next one! this.state = STATE_ANIM_LAST; this.lastWarp.start(); //copy over the final -> initial constraints int meshSize = this.firstMesh.meshSize; Point[][] fPoints = this.lastBlendMesh.getMesh(); Point[][] iPoints = this.lastMesh.getMesh(); for(int x = 0; x <= meshSize; x ++){ for(int y = 0; y <= meshSize; y ++){ iPoints[x][y].setTo(fPoints[x][y]); } } } } else if(this.state == STATE_ANIM_LAST){ this.lastWarp.tick(TIME_STEP); this.lastWarp.draw(); if(! this.lastWarp.isAnimating()){ // done! next one! this.state = STATE_ANIM_DONE; this.newText = new SlideText("click to: restart the animation restart the warping", this.slideFont, new Point(TEXT_X_START, TEXT_Y)); this.newText.setFinalPoint(new Point(TEXT_X_MIDDLE, TEXT_Y)); } } else if(this.state == STATE_ANIM_DONE){ this.newText.draw(); this.lastWarp.draw(); } //if(this.bMakeMovie){ loadPixels(); //this.mm.addFrame(pixels, width, height); //} } void keyPressed(){ if(key == ' '){ if(this.state == STATE_WARP_FIRST){ this.firstMesh.toggleConstraints(); } else if(this.state == STATE_WARP_LAST){ this.lastMesh.toggleConstraints(); } else if(this.state == STATE_WARP_BLEND_DOTS){ this.lastMesh.toggleConstraints(); } else if(this.state == STATE_WARP_BLEND_TWEAK){ this.firstBlendMesh.toggleConstraints(); } } else if(key == 'm'){ println("Starting movie"); } else if(key == 'M'){ //this.mm.finishMovie(); println("Ending movie"); } }