« My HD Crashed ! | Main | Final - Documentation and Special Thanks! »

Final - 4 week mark

Little creature

animated yellow monster.GIF

This is the monster that will run around the screen. He will do the following things:
a. run away from you. He runs away and flaps his arms as his feet move unreasonably fast.
b. if no one is trying to catch him, he stands around for a while.
c. after standing around, he'll get bored and start waving at you.
d. after a while, he'll taunt you, by sticking his tounge out at you.

The animation responds to mouse-x, y positions. It is a series of GIF images that are pulled dynamically in processing, depending on the state of the creature and his relationship with the user.

Motion Tracking
I decided to start all over. I discovered a reason not to use jitter: the JMyron library in processing! This library uses DirectX for video capturing, and so all my problems are solved. I am more comfortable with code than with graphical programming (Jitter), so I decided to start all over for the motion tracking part.

A JMyron is a camera object that uses directX and that allows us to specify things like how sensitive a camera is how often it adapts, etc. I relied heavily on the code examples that came with the library. But this is the basic logic: I take a picture of the current background before startting the motion tracking part. Then I call the differenceImage function of the camera object that will take a difference of the "control" image and the new image and finds the difference between. This differenced image is what I use for tracking. The differenced image will create white spots/areas where the differences are, and the JMyron will track white in the Matrix. All the points of change are then averaged to get a center point, or the average location of motion.

Camera Location
The camera is now located at the ceiling of the box, pointing downwards at a 20 degree angle. The plexi will be angled at 45 degree, and the monitor will be angled to create the illusion of a hollogram in the camera's direct line of sight.

Todo:
Now I need to build an enclosure to hide everything. I also need to make a button to reset things, and maybe (if I have time) allow the user to scroll through different hollographic characters using a variable restistor.

The Code

import JMyron.*;

JMyron m;//a camera object

//variables to maintain the floating green circle
float objx = 640; //160;
float objy = 350; //120;
float objdestx = 640; //160;
float objdesty = 350; //120;

//animated creature clips
AniSprite waving, walking, teasing, standing;
//float xpos, ypos;
float drag = 30.0;

int TEASE_STATE = 500;
boolean teaseState = false;
int teaseframes = 31;
int currentSt = 0;

int CAMERA_WIDTH = 320;
int CAMERA_HEIGHT = 240;

void setup()
{
size(1280, 800); //960);
background(0,0,0); //255, 204, 0);
frameRate(30);
waving = new AniSprite("wave", 17);
walking = new AniSprite("step", 9);
teasing = new AniSprite("tease", teaseframes);
standing = new AniSprite("stand", 11);

//capturing junk
m = new JMyron();//make a new instance of the object
m.start(CAMERA_WIDTH, CAMERA_HEIGHT);//start a capture at 320x240
m.trackColor(255,255,255,256*3-100);//track white
m.update(); //called once per frame, updates vision processing and camera updating
m.adaptivity(10); //how fast/often retina image adapts!
m.adapt();// immediately take a snapshot of the background for differencing
println("Myron " + m.version());
rectMode(CENTER);
noStroke();


}

void draw()
{

m.update();//update the camera view
drawCamera();

int[][] centers = m.globCenters();//get the center points
println("centers size = " + centers.length);
//draw all the dots while calculating the average.
float avX=0;
float avY=0;
for(int i=0;i fill(80);
rect(centers[i][0],centers[i][1],5,5);
avX += centers[i][0];
avY += centers[i][1];
}
if(centers.length-1>0){
avX/=centers.length-1;
avY/=centers.length-1;
}

//draw the average of all the points in red.
fill(255,0,0);
rect(avX,avY,5,5);

//update the location of monster
if(!(avX==0&&avY==0)&¢ers.length>0){
objdestx = avX*3.75;
objdesty = avY*3.75;
println("X = " + avX + ", Y = " + avY);
println("objx = " + objx);
println("objdestx - ojx = " + ( (objdestx - objx)/10.0f));
} //else there is no movement, pull out teasing here

objx += (objdestx-objx)/10.0f;
objy += (objdesty-objy)/10.0f;

objx = constrain(objx, 0, width - walking.getWidth());
objy = constrain(objy, 0, height - walking.getHeight());

/*
//DRAWING THE CREATURE
//think of difx as the new direction and drag as the speed /
float difx = objdestx - objx; //mouseX - xpos;
float dify = objdesty - objy; //mouseY - ypos;
if(abs(difx) > 1.0) {
objx = objx + difx/drag;
objx = constrain(objx, 0, width);
//xpos = xpos + difx/drag;
//xpos = constrain(xpos, 0, width);
}

if(abs(dify) > 1.0) {
objy = objy + dify/drag;
objy = constrain(objy, 0, width);
//ypos = ypos + dify/drag;
//ypos = constrain(ypos, 0, width);
}*/

background(0,0,0);

println("currentSt = " + currentSt);

// Display the sprite at the position xpos, ypos
/* if(mousePressed) {
//background(153, 153, 0);
//waving.display(xpos-waving.getWidth()/2, ypos);
//waving.display(objx, objy);
teasing.display(objx-waving.getWidth()/2, objy);
}
else */
if(centers.length == 0){

currentSt++;
if(currentSt == TEASE_STATE){
teaseState = true;
currentSt = 0;
}

if(teaseState){
if(currentSt <= teaseframes) teasing.display(objx, objy);
else {
currentSt = 0;
teaseState = false;
waving.display(objx, objy);
}
}
else {
//make monster wave at the user, but only after an interval of boredeom (just standing)
if((currentSt < 150) || ((currentSt > 300) && (currentSt < 400)) ) {
standing.display(objx, objy);
}else waving.display(objx, objy); //objx-waving.getWidth()/2, objy);
}

} else {
//background(255, 204, 0);
walking.display(objx, objy); //xpos-waving.getWidth()/2, ypos);
}
}


void drawCamera(){
//for debug:
//m.cameraImage returns reg image
//m.retinaImage returns image adapting to camera
//m.globsImage returns globs preview
//m.differenceImage returns image diff
int[] img = m.differenceImage(); //get the normal image of the camera
loadPixels();
//for(int i=0;i // pixels[i] = img[i]; //draw each pixel to the screen
//}
updatePixels();
}

/*
void mousePressed(){
m.settings();//click the window to get the settings
}*/

public void stop(){
m.stop();//stop the object
super.stop();
}

// Class for animating GIFs

class AniSprite
{
PImage[] ani;
int frame;
int numFrames;

AniSprite(String imageName, int frameCount) {
numFrames = frameCount;
ani = new PImage[numFrames];
loadImages(imageName);
}

void loadImages(String name) {
for(int i=0; i String imageName = name + i + ".gif";
ani[i] = loadImage(imageName);
}
}

void display(float xpos, float ypos)
{
frame = (frame+1)%numFrames;
image(ani[frame], xpos, ypos);
}

int getWidth() {
return ani[0].width;
}

int getHeight(){
return ani[0].height;
}
}

TrackBack

TrackBack URL for this entry:
http://itp.nyu.edu/~ye265/cgi-bin/mt/mt-tb.cgi/32

Post a comment

(If you haven't left a comment here before, you may need to be approved by the site owner before your comment will appear. Until then, it won't appear on the entry. Thanks for waiting.)