diff options
| author | Tim Redfern <tim@eclectronics.org> | 2012-08-21 15:44:11 +0100 |
|---|---|---|
| committer | Tim Redfern <tim@eclectronics.org> | 2012-08-21 15:44:11 +0100 |
| commit | 621674d6e9fb0024645cd0020c6afb51e4b4a7e9 (patch) | |
| tree | a9e4fbda9ff8afd13dab0228de83c7041101947c /gaunt01/src | |
| parent | fbc66a871153a8b85006e49f755cc8fb540781f7 (diff) | |
had enough
Diffstat (limited to 'gaunt01/src')
| -rw-r--r-- | gaunt01/src/main.cpp | 16 | ||||
| -rw-r--r-- | gaunt01/src/testApp.cpp | 1263 |
2 files changed, 1279 insertions, 0 deletions
diff --git a/gaunt01/src/main.cpp b/gaunt01/src/main.cpp new file mode 100644 index 0000000..1f3ac12 --- /dev/null +++ b/gaunt01/src/main.cpp @@ -0,0 +1,16 @@ +#include "ofMain.h" +#include "testApp.h" +#include "ofAppGlutWindow.h" + +//======================================================================== +int main( ){ + + ofAppGlutWindow window; + ofSetupOpenGL(&window, 1024,768, OF_FULLSCREEN ); // <-------- setup the GL context + printf("%ix%i on screen %ix%i\n",ofGetWidth(),ofGetHeight(),ofGetScreenWidth(),ofGetScreenHeight()); + // this kicks off the running of my app + // can be OF_WINDOW or OF_FULLSCREEN + // pass in width and height too: + ofRunApp( new testApp()); + +} diff --git a/gaunt01/src/testApp.cpp b/gaunt01/src/testApp.cpp new file mode 100644 index 0000000..beefce0 --- /dev/null +++ b/gaunt01/src/testApp.cpp @@ -0,0 +1,1263 @@ +#include "testApp.h" + +//-------------------------------------------------------------- +//units ~ 10cm +// +/* +Can use a floating point image or array to accumulate the screen and generate averaged background? + +Is this too much work for every frame? Should it be put in a seperate thread? + +*/ + +void testApp::setup(){ + + printf("setup: %ix%i on screen %ix%i\n",ofGetWidth(),ofGetHeight(),ofGetScreenWidth(),ofGetScreenHeight()); + + int windowMode = ofGetWindowMode(); + if(windowMode == OF_FULLSCREEN){ + this->windowWidth = ofGetScreenWidth(); + this->windowHeight = ofGetScreenHeight(); + } + else if(windowMode == OF_WINDOW){ + this->windowWidth = ofGetWidth(); + this->windowHeight = ofGetHeight(); + } + + mirror=true; + + bLearnBakground = true; + cam_angle=0; + threshold = 80; + + loadSettings("settings.xml"); + + vidGrabber.setVerbose(true); + if (vidGrabber.initGrabber(640,480)) { + hasCamera=true; + useCamera=true; + } + else + { + hasCamera=false; + useCamera=false; + vidPlayer.loadMovie(testmovie); //footage/ camera needs to be the same res as opencv planes and output + vidPlayer.setLoopState(OF_LOOP_NORMAL); + vidPlayer.play(); + } + + /* + accumImg.allocate(640,480); + + bgImg.allocate(640,480); + bgImg.setUseTexture(true); +
+
+ + grayImage.allocate(640,480); + grayBg.allocate(640,480); + */ + + colorImg.allocate(640,480); + colorImg.setUseTexture(true); + currentFrame.allocate(CAM_WIDTH_FG, CAM_HEIGHT_FG); + background.allocate(CAM_WIDTH_FG, CAM_HEIGHT_FG); + background.setUseTexture(true); + + grayFrame.allocate(CAM_WIDTH_FG, CAM_HEIGHT_FG); + grayBg.allocate(CAM_WIDTH_FG, CAM_HEIGHT_FG); + grayDiff.allocate(CAM_WIDTH_FG, CAM_HEIGHT_FG); + + mogoutput.allocate(CAM_WIDTH_FG, CAM_HEIGHT_FG); + + learningRate = 0.01f; + bFirstFrame=true; + + diffchannel=chan_V; + hsvback = cvCreateImage(cvGetSize(currentFrame.getCvImage()), currentFrame.getCvImage()->depth, currentFrame.getCvImage()->nChannels); + //backchan = cvCreateImage(cvGetSize(currentFrame.getCvImage()), 8, 1); + + removeShadows=false; + shadowThreshold=10; + //////////////////////////// + + blobsManager.normalizePercentage = 0.7; + blobsManager.giveLowestPossibleIDs = false; + blobsManager.maxUndetectedTime = 500; + blobsManager.minDetectedTime = 500; + blobsManager.debugDrawCandidates = true; + + ofVec3f centre=ofVec3f(windowWidth/2,0,0); + ofVec3f normal=ofVec3f(0,0,-1); + ray=ofRay(); + plane=ofPlane(centre,normal); + plane.color=ofColor(255,255,255); + + projector=ofProjector(2.0f, ofVec2f(0.0f, 0.0f),windowWidth,windowHeight); //1.535f + projector.setPosition(windowWidth/2,windowHeight/2,-windowWidth); + projector.lookAt(ofVec3f(windowWidth/2,windowHeight/2,0),ofVec3f(0, -1, 0)); + + cam=ofCamera(); + cam.setPosition(windowWidth/2,windowHeight/2,-windowWidth); + cam.lookAt(ofVec3f(windowWidth/2,windowHeight/2,0),ofVec3f(0, -1, 0)); + cam.setFov(41.1); //39.85); //53.13); + cam.cacheMatrices(); //stop error messages - changed API? + + testpts=new ofVec3f[4]; + + bounds=new ofPlane[4]; + + //trapDoor=trapdoor(screen2plane(ofVec2f(windowWidth,0)),screen2plane(ofVec2f(windowWidth,windowHeight)),35); + trapdoorSize=35; + trapdoorSlotSize=50; + + + trapdoorTime=10.0; //time per trapdoor; + + + + mode=PLAY; + + drawStats=false; + + bgnum=1000; + firstframe=true; + + light.setPosition(windowWidth,0,windowHeight); + light.enable(); + + drawingborder=false; + + billboards=new ofImage[4]; + billboards[0].loadImage("GUI_title.png"); + billboards[1].loadImage("GUI_objective.png"); + billboards[2].loadImage("GUI_gotya.png"); + billboards[3].loadImage("GUI_instructions.png"); + + for (int i=0;i<4;i++) { + billboards[i].setAnchorPercent(0.5,0.5); + } + scaleFactor=ofVec2f(windowWidth/1280.0f,windowHeight/768.0f); + + gameState=TITLES; //PLAYING; //TITLES; // + + segTimes[TITLES]=4.0; + segTimes[EXPLAIN]=5.0; + segTimes[PLAYING]=60.0; + segTimes[GOTCHA]=4.0; + + gameStart=ofGetElapsedTimef(); + + sounds=new ofSoundPlayer[1]; + sounds[0].loadSound("arp5.mp3"); //game start + + + doorsounds=new ofSoundPlayer[4]; + doorsounds[0].loadSound("creeky door short1.wav"); + doorsounds[1].loadSound("creeky door short2.wav"); + doorsounds[2].loadSound("creeky door short3.wav"); + doorsounds[3].loadSound("voice falling down hole.wav"); + + cam.begin(); + + + //mog=cv::BackgroundSubtractorMOG(100,10,.1,.1); + +
+ cam.end(); + +} + +ofVec2f testApp::screen2plane(ofVec2f screenpos){ + ofVec3f p; + ray=projector.castPixel(screenpos.x,screenpos.y); + bool hit = plane.intersect(ray,p); + return ofVec2f(p.x,pow(pow(p.y,2)+pow(p.z,2),0.5f)); +} +ofVec3f testApp::plane2world(ofVec2f planepos){ + return ofVec3f(planepos.x,planepos.y,0); +} +bool testApp::rectsCross(ofRectangle rect1,ofRectangle rect2) { + bool overlap=true; //must overlap in x and y + if (rect1.x<rect2.x) { + if (rect1.x+rect1.width<rect2.x) overlap = false; + } + else if (rect2.x<rect1.x) { + if (rect2.x+rect2.width<rect1.x) overlap = false; + } + if (overlap) { //still possible + if (rect1.y<rect2.y) { + if (rect1.y+rect1.height<rect2.y) overlap = false; + } + else if (rect2.y<rect1.y) { + if (rect2.y+rect2.height<rect1.y) overlap = false; + } + } + return overlap; +} + +void testApp::tessGround(int num){ + //updates ground and makes texture coords; + + if (num==0) { + groundlines.clear(); + ofPolyline pol; + pol.addVertex(0,0); + pol.addVertex(windowWidth,0); + pol.addVertex(windowWidth,windowHeight); + pol.addVertex(0,windowHeight); + pol.close(); + groundlines.push_back(pol); + } + + vector<ofVec2f> corners=trapdoors[num].getCorners(); + ofPolyline pol2; + for (int i=0;i<corners.size();i++) { + + ofVec3f cw=ofVec3f(corners[i].x,corners[i].y,0).rotated(cam_angle,ofVec3f(1,0,0)); + ofVec3f s=cam.worldToScreen(cam.worldToScreen(cw)); + //printf("corner %i: %f,%f to %f,%f,%f\n",i,corners[i].x,corners[i].y,s.x/s.z,s.y/s.z,s.z); + pol2.addVertex(s.x,s.y); + } + pol2.close(); + groundlines.push_back(pol2); + + ground=ofMesh(); + tess.tessellateToMesh(groundlines,OF_POLY_WINDING_ODD,ground,true); + for (int i=0;i<ground.getNumVertices();i++) { + ofVec3f v=ground.getVertex(i); + ground.addTexCoord(ofVec2f(v.x/windowWidth,v.y/windowHeight)); + } + +} + +void testApp::makeGround(int doornumber){ + //create ground mesh with hole for trapdoor + + //IS NOT WORKING!?? + //it is building a hole somewhere.. whats.. the.. problem.. + ground=ofMesh(); + ground.addVertex(ofVec3f(0,0,0)); + ground.addTexCoord(ofVec2f(0,0)); + ground.addVertex(ofVec3f(windowWidth,0,0)); + ground.addTexCoord(ofVec2f(1,0)); + ground.addVertex(ofVec3f(windowWidth,windowHeight,0)); + ground.addTexCoord(ofVec2f(1,1)); + ground.addVertex(ofVec3f(0,windowHeight,0)); + ground.addTexCoord(ofVec2f(0,1)); + + vector<ofVec2f> corners=trapdoors[doornumber].getCorners(); + ofVec2f screenCorners[4]; + + for (int i=0;i<corners.size();i++) { + + ofNode axis; + ofNode c; + c.setParent(axis); + + c.setPosition(corners[i].x,corners[i].y,0); + + axis.rotate(cam_angle,1,0,0); + + ofVec3f p=c.getGlobalPosition(); + + testpts[i]=p; + ofVec3f s=cam.worldToScreen(p); + //printf("corner %i: %f,%f,%f\n",i,s.x,s.y,s.z); + screenCorners[i]=ofVec2f(s.x,s.y); + + ground.addVertex(s); + ground.addTexCoord(ofVec2f(s.x/windowWidth,s.y/windowHeight)); + } + //join a quad for each side + // the 2 rear sides should always point towards the rear + for (int i=0;i<3;i++) { + ground.addTriangle(i,i+4,i+5); + ground.addTriangle(i+5,i+1,i); + } + ground.addTriangle(3,7,0); + ground.addTriangle(7,4,0); + float x=min(screenCorners[0].x,screenCorners[3].x); + float y=min(screenCorners[0].y,screenCorners[1].y); + float w=max(screenCorners[1].x,screenCorners[2].x)-x; + float h=max(screenCorners[2].y,screenCorners[3].y)-y; + //trapDoor.setBoundingRect(x,y,w,h); +} + + +void testApp::updatePlane(){ + //setup screen for new incline angle + plane.setNormal(ofVec3f(0,sin(cam_angle*DEG_TO_RAD),-cos(cam_angle*DEG_TO_RAD))); + + //bird intersect planes + ofVec2f l=ofVec2f(windowWidth/20,windowHeight/2); + ofRay r=projector.castPixel(l.x,l.y); + ofVec3f p; + if (plane.intersect(r,p)) printf("found ground plane intersection 1 at %f,%f,%f\n",p.x,p.y,p.z); + else printf("bound plane 1 not found\n"); + ofVec3f pn=(p-projector.getGlobalPosition()).getPerpendicular(ofVec3f(0,-1,0)); + bounds[0]=ofPlane(p,pn); //,pn,ofVec2f(1000,1000)); + + l=ofVec2f(windowWidth/2,windowHeight/20); + r=projector.castPixel(l.x,l.y); + if (plane.intersect(r,p)) printf("found ground plane intersection 2 at %f,%f,%f\n",p.x,p.y,p.z); + else printf("bound plane 2 not found\n"); + pn=(p-projector.getGlobalPosition()).getPerpendicular(ofVec3f(1,0,0)); + bounds[1]=ofPlane(p,pn); //,-pn,ofVec2f(1000,1000)); + + l=ofVec2f(19*windowWidth/20,windowHeight/2); + r=projector.castPixel(l.x,l.y); + if (plane.intersect(r,p)) printf("found ground plane intersection 3 at %f,%f,%f\n",p.x,p.y,p.z); + else printf("bound plane 3 not found\n"); + pn=(p-projector.getGlobalPosition()).getPerpendicular(ofVec3f(0,1,0)); + bounds[2]=ofPlane(p,pn); //,-pn,ofVec2f(1000,1000)); + + l=ofVec2f(windowWidth/2,19*(windowHeight/20)); + r=projector.castPixel(l.x,l.y); + if (plane.intersect(r,p)) printf("found ground plane intersection 4 at %f,%f,%f\n",p.x,p.y,p.z); + else printf("bound plane 4 not found\n"); + pn=(p-projector.getGlobalPosition()).getPerpendicular(ofVec3f(-1,0,0)); + bounds[3]=ofPlane(p,pn); //,-pn,ofVec2f(1000,1000)); + + l=ofVec2f(windowWidth/2,windowHeight/2); + r=projector.castPixel(l.x,l.y); + if (plane.intersect(r,centre)) printf("found centre point at %f,%f,%f\n",centre.x,centre.y,centre.z); + else printf("centre point not found\n"); + ofVec3f c=centre.rotated(cam_angle,ofVec3f(-1,0,0)); + + Bird.setBounds(bounds); + Bird.setCentre(ofVec2f(c.x,c.y)); + + +// vector<trapdoor> trapdoors; +// float trapdoorSize; +// float trapdoorSlotSize; +// int numtrapdoorSlots; + +//create all trapdoors at once, deactivated. +//shuffle them +//at each timeout, pick the next door to activate (check if within bounds) and rebuild ground with holes +//on update, check all active doors against all players +//when a falling in sequence is over, start again + + trapdoors.clear(); + + l=ofVec2f(windowWidth/2,19*windowHeight/20); + r=projector.castPixel(l.x,l.y); + plane.intersect(r,p); + float closestY=p.rotated(cam_angle,ofVec3f(-1,0,0)).y; + numtrapdoorSlots=closestY/trapdoorSlotSize; + + //get middle position in the slot on the ground visible at front of screen + ofVec3f rp=ofVec3f(windowWidth/2,closestY-(0.5*trapdoorSlotSize),0); + //translate to the screen + ofVec3f sp=cam.worldToScreen(rp.rotated(cam_angle,ofVec3f(1,0,0))); + + //printf("front slot: %f,%f to %f,%f,%f\n",rp.x,rp.y,sp.x,sp.y,sp.z); + + //get point at left of this line + //project back on ground + ofVec2f gb=screen2plane(ofVec2f(windowWidth/8,sp.y)); + r=projector.castPixel(sp.x,sp.y); + plane.intersect(r,p); + float range=(((windowWidth/2)-p.x)*2); + + for (int i=0;i<numtrapdoorSlots;i++) { + //get middle position in the slot on the ground visible on screen + ofVec3f rp=ofVec3f(windowWidth/2,closestY-((i+0.5)*trapdoorSlotSize),0); + //randomise horizontal pos + rp.x=ofRandom(trapdoorSlotSize*5)-(trapdoorSlotSize*2.5)+(+windowWidth/2); + + //gb.x=ofRandom((windowWidth-gb.x)*2)+gb.x; + if (border.size()<3||!OutsidePolygon(border,ofPoint(rp.x,rp.y))) { + trapdoors.push_back(trapdoor(ofVec2f(rp.x,rp.y),trapdoorSize)); + } + } + random_shuffle ( trapdoors.begin(), trapdoors.end() ); + + trapdoorCounter=0; + trapdoors[trapdoorCounter].active=true; + + //makeGround(0); + + + + + tessGround(0); + + /* + //create ground mesh with hole for trapdoor + + //IS NOT WORKING!?? + //it is building a hole somewhere.. whats.. the.. problem.. + /* + ground=ofMesh(); + ground.addVertex(ofVec3f(0,0,0)); + ground.addTexCoord(ofVec2f(0,0)); + ground.addVertex(ofVec3f(windowWidth,0,0)); + ground.addTexCoord(ofVec2f(1,0)); + ground.addVertex(ofVec3f(windowWidth,windowHeight,0)); + ground.addTexCoord(ofVec2f(1,1)); + ground.addVertex(ofVec3f(0,windowHeight,0)); + ground.addTexCoord(ofVec2f(0,1)); + + vector<ofVec2f> corners=trapdoors[0].getCorners(); + ofVec2f screenCorners[4]; + + for (int i=0;i<corners.size();i++) { + + ofNode axis; + ofNode c; + c.setParent(axis); + + c.setPosition(corners[i].x,corners[i].y,0); + + axis.rotate(cam_angle,1,0,0); + + ofVec3f p=c.getGlobalPosition(); + + testpts[i]=p; + ofVec3f s=cam.worldToScreen(p); + //printf("corner %i: %f,%f,%f\n",i,s.x,s.y,s.z); + screenCorners[i]=ofVec2f(s.x,s.y); + + ground.addVertex(s); + ground.addTexCoord(ofVec2f(s.x/windowWidth,s.y/windowHeight)); + } + //join a quad for each side + // the 2 rear sides should always point towards the rear + for (int i=0;i<3;i++) { + ground.addTriangle(i,i+4,i+5); + ground.addTriangle(i+5,i+1,i); + } + ground.addTriangle(3,7,0); + ground.addTriangle(7,4,0); + float x=min(screenCorners[0].x,screenCorners[3].x); + float y=min(screenCorners[0].y,screenCorners[1].y); + float w=max(screenCorners[1].x,screenCorners[2].x)-x; + float h=max(screenCorners[2].y,screenCorners[3].y)-y; + //trapDoor.setBoundingRect(x,y,w,h); +*/ + +} + +//-------------------------------------------------------------- +void testApp::update(){ + + bool bNewFrame = false; + + if (useCamera) { + vidGrabber.grabFrame(); + bNewFrame = vidGrabber.isFrameNew(); + }else { + vidPlayer.idleMovie(); + bNewFrame = vidPlayer.isFrameNew(); + } + + if (bNewFrame){ + + if (useCamera) { + colorImg.setFromPixels(vidGrabber.getPixels(), 640,480); + //accumImg.setFromPixels(vidGrabber.getPixels(), 640,480); + }else { + colorImg.setFromPixels(vidPlayer.getPixels(), 640,480); + //accumImg.setFromPixels(vidPlayer.getPixels(), 640,480); + } + + if (mirror) colorImg.mirror(false,true); + + colorImg.updateTexture(); + + /* +
+ grayImage = colorImg; + + if (firstframe) { + accumImg=grayImage; + firstframe=false; + sounds[0].play(); + } + else { + accumImg.addWeighted( grayImage, 1.0/bgnum ); + //accumImg/=(1.0+(0.25/bgnum)); + } + + bgImg=accumImg; + bgImg.updateTexture(); + + grayDiff.clear(); + grayDiff.allocate(640,480); + + // take the abs value of the difference between background and incoming and then threshold: + grayDiff.absDiff(bgImg, grayImage); + grayDiff.threshold(threshold); + //grayDiff.adaptiveThreshold( threshold); //int blockSize, int offset=0,bool invert=false, bool gauss=false); + //grayDiff.erode_3x3(); + grayDiff.resize(windowWidth,windowHeight); + + // find contours which are between the size of 20 pixels and 1/3 the w*h pixels. + // also, find holes is set to true so we will get interior contours as well.... + + //hard coded size threshold of 100 pix + contourFinder.findContours(grayDiff, 200, (640*480)/3, 20, false); // don't find holes + + */ + + cv::Mat img = colorImg.getCvImage(); + + + + + //if (frameno%1==0) { //I THINK THIS APPROACH IS OK to attempt to lower cpu hit from accumulating? + + //cv::Rect roi(0, 0, 32, 32); //doesn't seem that easy to apply the ROI weighted and you still have to convert a whole image each frame? + + //cv::Mat imgroi = img(roi); + + if (bFirstFrame) { + img.convertTo(accumulator, CV_32FC3); + bFirstFrame=false; + } + + cv::Mat im3; + img.convertTo(im3, CV_32FC3); + + + + //accumulator; + accumulateWeighted(im3, accumulator, max(1.0f/(ofGetElapsedTimef()*30.0f),learningRate)); + accumulator.convertTo(outmat,CV_8UC3); + + IplImage* tmp = new IplImage(outmat); + background=tmp; + background.updateTexture(); + + //printf("tmp: %ix%i channels: %i depth:%i\n",tmp->width,tmp->height,tmp->nChannels,tmp->depth); + + + //get correct channel into backchan + + + + vector<cv::Mat> chans; + + //to remove shadows, need hsv of foreground and background + if (diffchannel>chan_B||removeShadows) cvtColor(outmat, hsvback, CV_BGR2HSV); + switch (diffchannel) { + case chan_R: + split(outmat,chans); + chans[0].copyTo(backchan); + break; + case chan_G: + split(outmat,chans); + chans[1].copyTo(backchan); + break; + case chan_B: + split(outmat,chans); + chans[2].copyTo(backchan); + break; + case chan_H: + split(hsvback,chans); + chans[0].copyTo(backchan); + break; + case chan_S: + split(hsvback,chans); + chans[1].copyTo(backchan); + break; + case chan_V: + split(hsvback,chans); + chans[2].copyTo(backchan); + break; + } + + + tmp = new IplImage(backchan); + grayBg = tmp; + + //} + //first, optionally remove shadows from FG + //possibly use 1/4 screen res? + + //to remove shadows, need hsv of foreground and background + if (diffchannel>chan_B||removeShadows) cvtColor(img, hsvfront, CV_BGR2HSV); + + cv::Mat outimg; + + if (removeShadows) { + vector<cv::Mat> slicesFront, slicesBack; + cv::Mat valFront, valBack, satFront, satBack; + + // split image to H,S and V images + split(hsvfront, slicesFront); + split(hsvback, slicesBack); + + slicesFront[2].copyTo(valFront); // get the value channel + slicesFront[1].copyTo(satFront); // get the sat channel + + slicesBack[2].copyTo(valBack); // get the value channel + slicesBack[1].copyTo(satBack); // get the sat channel + + int x,y; + for(x=0; x<currentFrame.getWidth(); ++x) { + for(y=0; y<currentFrame.getHeight(); ++y) { + bool sat = ((satFront.at<cv::Vec3b>(y,x)[0] > satBack.at<cv::Vec3b>(y,x)[0]-shadowThreshold) && + (satFront.at<cv::Vec3b>(y,x)[0] < satBack.at<cv::Vec3b>(y,x)[0]+shadowThreshold)); + + if(sat && (valFront.at<cv::Vec3b>(y,x)[0] < valBack.at<cv::Vec3b>(y,x)[0])) { + hsvfront.at<cv::Vec3b>(y,x)[0]= hsvback.at<cv::Vec3b>(y,x)[0]; + hsvfront.at<cv::Vec3b>(y,x)[1]= hsvback.at<cv::Vec3b>(y,x)[1]; + hsvfront.at<cv::Vec3b>(y,x)[2]= hsvback.at<cv::Vec3b>(y,x)[2]; + } + + } + } + + //convert back into RGB if necessary + + if (diffchannel<chan_H) cvtColor(hsvfront, outimg, CV_HSV2BGR); + else outimg=hsvfront; + + }else { + outimg=img; + } + + + //select correct channel for comparison and put into grayFrame + + //vector<cv::Mat> chans; + split(outimg,chans); + + switch (diffchannel) { + case chan_R: + chans[0].copyTo(frontchan); + break; + case chan_G: + chans[1].copyTo(frontchan); + break; + case chan_B: + chans[2].copyTo(frontchan); + break; + case chan_H: + chans[0].copyTo(frontchan); + break; + case chan_S: + chans[1].copyTo(frontchan); + break; + case chan_V: + chans[2].copyTo(frontchan); + break; + } + + //IplImage* tmp = new IplImage(outmat); + tmp = new IplImage(frontchan); + grayFrame = tmp; + + grayDiff.clear(); + grayDiff.allocate(640,480); + + // take the abs value of the difference between background and incoming and then threshold: + grayDiff.absDiff(grayBg, grayFrame); + grayDiff.threshold(threshold); + //grayDiff.adaptiveThreshold( threshold,20,true,false); //int blockSize, int offset=0,bool invert=false, bool gauss=false); + //grayDiff.erode_3x3(); + //grayDiff.resize(windowWidth,windowHeight); + + /* + + //MOG + + mog(img, outmat, mogf); + + + + + + // Complement the image + //cv::threshold(outmat, output, threshold, 255, cv::THRESH_BINARY_INV); + IplImage* tmp1 = new IplImage(outmat); + //printf("tmp: %ix%i channels: %i depth:%i\n",tmp->width,tmp->height,tmp->nChannels,tmp->depth); + //printf("grayDiff: %ix%i channels: %i depth:%i\n",grayDiff.getCvImage()->width,grayDiff.getCvImage()->height,grayDiff.getCvImage()->nChannels,grayDiff.getCvImage()->depth); + grayDiff=tmp1; //copy to ofx + + */ + + + + if (mode==CHECKACCUM) colorImg=grayDiff; + + grayDiff.resize(windowWidth,windowHeight); //wasteful?? + + + + contourFinder.findContours(grayDiff, 500, (640*480)/3, 20,false); // find holes + + blobsManager.update(contourFinder.blobs); + //check players against blob ids - bland do ray casting, update players + //ids are always in order + //players can be a map vs ID + //check if a key exists in a map - map::count + //do we purge them or just stop drawing them? is it a problem inheriting tesselator re memory? + //if we keep them we can have a 'loserboard' + set<int> ids; + for(int i=0;i<blobsManager.blobs.size();i++){ + ofxCvBlob blob = blobsManager.blobs.at(i); + ids.insert(blobsManager.blobs.at(i).id); + ofRectangle r=blob.boundingRect; + ofVec2f blobBase=ofVec2f(r.x+(r.width/2),r.y+r.height-(r.width/2)); + ofVec3f pp,rp; + ray=projector.castPixel(blobBase.x,blobBase.y); + bool hit = plane.intersect(ray,pp); + rp=pp.getRotated(cam_angle,ofVec3f(-1,0,0)); + players[blobsManager.blobs.at(i).id].setScreenPosition(blobBase); + players[blobsManager.blobs.at(i).id].setWorldPosition(ofVec3f(rp.x,rp.y,0)); + players[blobsManager.blobs.at(i).id].update(blob); //create model + } + map<int,player>::iterator it; + for (it=players.begin();it!=players.end();it++) { + if (ids.find(it->first)==ids.end()||(border.size()>3&&OutsidePolygon(border,ofPoint(it->second.getWorldPosition().x,it->second.getWorldPosition().y)))) it->second.active=false; + else it->second.active=true; + } + } + for (int i=0;i<trapdoorCounter;i++) { + if (trapdoors[i].checkUpdate(players)) { + //makeGround(i); + int whichsound=(int)ofRandom(2.9999999); + doorsounds[whichsound].play(); + doorsounds[3].play(); //falling down hole + if (gameState=PLAYING) { + gameState=GOTCHA; + gameStart=ofGetElapsedTimef(); + } + } + } + + if (gameState>EXPLAIN) Bird.update(players,cam_angle); + +} + +//-------------------------------------------------------------- +void testApp::draw(){ + + glDisable(GL_LIGHTING); + ofBackground(0,0,0); + cam.begin(); + glDisable(GL_DEPTH_TEST); + ofSetHexColor(0xffffff); + glDisable(GL_BLEND); + + if (gameState<PLAYING||mode==CHECKACCUM) colorImg.draw(0,0,windowWidth,windowHeight); + + else { + + //trapdoor logic + if (ofGetElapsedTimef()-trapdoorTimer>trapdoorTime) { + if (trapdoors.size()>trapdoorCounter+1) { + trapdoorCounter++; + trapdoorTimer=ofGetElapsedTimef(); + tessGround(trapdoorCounter); + } + //else updatePlane(); + } + + ofSetHexColor(0xffffff); + ofPushMatrix(); + ofRotate(cam_angle,1,0,0); + //trapDoor.draw(); + for (int i=0;i<=trapdoorCounter;i++) { + trapdoors[i].draw(); + } + ofPopMatrix(); + +//should be in front with holes being recreated for activated trapdoors + ofSetHexColor(0xffffff); + if (mode==CALIBRATE) bindTexture(colorImg); + else bindTexture(background); + ground.draw(); + if (mode==CALIBRATE) unbindTexture(colorImg); + else unbindTexture(background); + + ofPushMatrix(); + ofRotate(cam_angle,1,0,0); + Bird.drawShadow(); + ofPopMatrix(); + + glDisable(GL_DEPTH_TEST); + ofSetHexColor(0xffffff); + ofPushMatrix(); + ofRotate(cam_angle,1,0,0); + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + for (int i=0;i<=trapdoorCounter;i++) { + trapdoors[i].drawSplash(cam_angle); + + } + + glDisable(GL_BLEND); + ofPopMatrix(); + + if (mode!=CHECKACCUM) { + glDisable(GL_DEPTH_TEST); + ofSetHexColor(0xffffff); + bindTexture(colorImg); //colorImg.getTextureReference().bind(); + map<int,player>::iterator it; + for(int i=0;i<blobsManager.blobs.size();i++){ + //if(players[blobsManager.blobs.at(i).id].active) + players[blobsManager.blobs.at(i).id].draw(); + } + unbindTexture(colorImg); + } + + glEnable(GL_LIGHTING); + + ofPushMatrix(); + ofRotate(cam_angle,1,0,0); + Bird.draw(); + ofPopMatrix(); + + glDisable(GL_LIGHTING); + } + + float gameTime=ofGetElapsedTimef()-gameStart; + + switch(gameState) { + case TITLES: + case EXPLAIN: + if (gameTime>segTimes[gameState]) { + gameState++; + gameStart=ofGetElapsedTimef(); + gameTime=0.0f; + updatePlane(); + } + break; + case PLAYING: + if (gameTime>segTimes[gameState]) { + gameState=TITLES; + sounds[0].play(); + gameStart=ofGetElapsedTimef(); + gameTime=0.0f; + trapdoorTimer=ofGetElapsedTimef(); + } + break; + case GOTCHA: + if (gameTime>segTimes[gameState]) { + gameState=PLAYING; + gameStart=ofGetElapsedTimef(); + gameTime=0.0f; + updatePlane(); //for new trapdoors + } + break; + } + + float segElapsed=pow(gameTime/segTimes[gameState],2); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + switch(gameState) { + case TITLES: + billboards[0].draw(windowWidth/6 + ,scaleFactor.y*((-billboards[0].height/2)+(billboards[0].height*pow(sin(segElapsed*PI),0.4))) + ,billboards[0].width*scaleFactor.x + ,billboards[0].height*scaleFactor.y); + break; + /* + case CREDIT: + billboards[1].draw(windowWidth/6 + ,windowHeight+(scaleFactor.y*((billboards[1].height/2)-(billboards[1].height*pow(sin(segElapsed*PI),0.4)))) + ,billboards[1].width*scaleFactor.x + ,billboards[1].height*scaleFactor.y); + break; + */ + case EXPLAIN: + billboards[1].draw(windowWidth/2 + ,scaleFactor.y*((-billboards[1].height/2)+(billboards[1].height*pow(sin(segElapsed*PI),0.4))) + ,billboards[1].width*scaleFactor.x + ,billboards[1].height*scaleFactor.y); + break; + case PLAYING: + break; + case GOTCHA: + billboards[2].draw(windowWidth/2 + ,scaleFactor.y*((-billboards[2].height/2)+(billboards[2].height*pow(sin(segElapsed*PI),0.4))) + ,billboards[2].width*scaleFactor.x + ,billboards[2].height*scaleFactor.y); + break; + } + glDisable(GL_BLEND); + + + switch(mode) { + case PLAY: + + + + break; + case CALIBRATE: + case CHECKACCUM: + + ofSetHexColor(0xffffff); + ofPushMatrix(); + ofRotate(cam_angle,1,0,0); + for (float i=0;i<=windowWidth;i+=windowWidth/10) { + glBegin(GL_LINES); + glVertex3f(i,0,0); + glVertex3f(i,windowWidth,0); + glEnd(); + glBegin(GL_LINES); + glVertex3f(0,i,0); + glVertex3f(windowWidth,i,0); + glEnd(); + } + + ofVec2f pp=screen2plane(pos); + //ofSphere(pp.x,pp.y,0,5); + ofPopMatrix(); + + ofPushMatrix(); + ofRotate(cam_angle,1,0,0); + for (int i=0;i<trapdoors.size();i++) { + trapdoors[i].drawDebug(); + } + //trapDoor.drawDebug(); + ofPopMatrix(); + + if (gameState==PLAYING) Bird.drawDebug(); + + ofSetHexColor(0x77ff77); + + + ofVec3f bp; + for (int i=0;i<4;i++) { + bounds[i].draw(); + if (bounds[i].intersect(Bird.pointer,bp)) { + char numStr[16]; + sprintf(numStr, "%4.1f", (bp-Bird.position.rotated(cam_angle,ofVec3f(1,0,0))).length()); + ofVec3f sc=cam.worldToScreen(bp); + ofDrawBitmapString(numStr, sc.x, sc.y); + } + //ofLine(bounds[i].getCenter(),bounds[i].getCenter()+(bounds[i].getNormal()*100)); + //normals sorted + } + ofSetHexColor(0xffff77); + char numStr[16]; + sprintf(numStr, "%4.1f", Bird.centrehead); + ofVec3f sc=cam.worldToScreen(Bird.position); + ofDrawBitmapString(numStr, sc.x, sc.y); + + for(int i=0;i<Bird.playpos.size();i++) { + if (abs(Bird.playhead[i])<30) ofSetHexColor(0x77ffff); + else ofSetHexColor(0x555555); + ofPushMatrix(); + ofRotate(cam_angle,1,0,0); + + ofLine(Bird.position,Bird.playpos[i]); + + ofPopMatrix(); + char numStr[10]; + sprintf(numStr, "%4.1f", Bird.playdist[i]); + ofVec3f sc=cam.worldToScreen(ofVec3f((Bird.position.x+Bird.playpos[i].x)/2,(Bird.position.y+Bird.playpos[i].y)/2,(Bird.position.z+Bird.playpos[i].z)/2).rotated(cam_angle,ofVec3f(1,0,0))); + ofDrawBitmapString(numStr, sc.x, sc.y); + } + + for(int i=0;i<blobsManager.blobs.size();i++){ + + ofxCvBlob blob = blobsManager.blobs.at(i); + blob.draw(0,0); + ofPoint p=blob.centroid; + ofSetHexColor(0xffff00); + char numStr[16]; + sprintf(numStr, "%i", blobsManager.blobs[i].id); + ofDrawBitmapString(numStr, blob.boundingRect.x, blob.boundingRect.y); + + /* + ofPushMatrix(); + ofRotate(cam_angle,1,0,0); + ofTranslate(players[blobsManager.blobs.at(i).id].getWorldPosition()); + ofBox(0,-10,0,20); + //TODO get this into plane axis + ofPopMatrix(); + */ + + // + } + if (border.size()>1) { + ofSetHexColor(0x00ff00); + ofPushMatrix(); + ofRotate(cam_angle,1,0,0); + for (int i=0;i<border.size();i++) { + ofLine(border[i],border[(i+1)%border.size()]); + } + ofPopMatrix(); + } + + + + + break; + } + if (drawStats||mode==CALIBRATE) { + ofSetHexColor(0xffffff); + char reportStr[1024]; + sprintf(reportStr, "threshold %i\nfps: %3.1f\n%s",threshold,ofGetFrameRate(),removeShadows?"Removing shadows":"NOT removing shadows"); //\nnum blobs found %i, fps: %f", threshold, contourFinder.nBlobs, ofGetFrameRate()); + ofDrawBitmapString(reportStr, 10, windowHeight-35); + /* + char numStr[16]; + for(int i=0;i<blobsManager.blobs.size();i++){ + sprintf(numStr, "%i", blobsManager.blobs[i].id); + ofDrawBitmapString(numStr, 10+(i*30), windowHeight-55); + } + */ + } + cam.end(); + if (drawInstructions) { + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + billboards[3].draw(windowWidth/2,windowHeight/2); + glDisable(GL_BLEND); + } +} + +//-------------------------------------------------------------- +void testApp::keyPressed(int key){ + + switch (key){ + case '+': + threshold ++; + if (threshold > 255) threshold = 255; + break; + case '-': + threshold --; + if (threshold < 0) threshold = 0; + break; + case 'a': + cam_angle+=1; + updatePlane(); + break; + case 'z': + case 'Z': + cam_angle-=1; + updatePlane(); + break; + case 'q': + case 'Q': + drawStats=!drawStats; + break; + case 'm': + case 'M': + mirror=!mirror; + break; + case 's': + case 'S': + saveSettings("settings.xml"); + break; + case 'i': + case 'I': + drawInstructions=!drawInstructions; + break; + case '9': + mode=PLAY; + break; + case '0': + mode=CALIBRATE; + break; + case '8': + mode=CHECKACCUM; + break; + + case '1': + diffchannel = chan_R; + break; + case '2': + diffchannel = chan_G; + break; + case '3': + diffchannel = chan_B; + break; + case '4': + diffchannel = chan_H; + break; + case '5': + diffchannel = chan_S; + break; + case '6': + diffchannel = chan_V; + break; + + + case 'r': + case 'R': + removeShadows=!removeShadows; + printf(removeShadows?"removing shadows\n":"not removing shadows\n"); + break; + +/* + case '1': + if (Bird.currentseq!="hover") { + //mesh.sequences["trans_flaphover"].stopAt(0.3); + //mesh.sequences["trans_flaphover"].start(); + Bird.model.sequences[Bird.currentseq].fadeout(0.5); + Bird.model.sequences["hover"].fadein(0.5); + Bird.currentseq="hover"; + } + break; + case '2': + if (Bird.currentseq!="flap") { + //mesh.sequences["trans_hoverflap"].stopAt(0.3); + //mesh.sequences["trans_hoverflap"].start(); + Bird.model.sequences[Bird.currentseq].fadeout(0.5); + Bird.model.sequences["flap"].fadein(0.5); + Bird.currentseq="flap"; + } + break; + case '3': + if (Bird.currentseq!="swoop") { + //mesh.sequences["trans_hoverflap"].stopAt(0.3); + //mesh.sequences["trans_hoverflap"].start(); + Bird.model.sequences[Bird.currentseq].fadeout(0.25); + Bird.model.sequences["swoop_trans"].fadein(0.25); + Bird.model.sequences["swoop_trans"].stopTime=ofGetElapsedTimef()+1.0; + Bird.model.sequences["swoop"].startAt(1.0); + Bird.currentseq="swoop"; + } + break; + case '4': + if (Bird.currentseq!="attack") { + //mesh.sequences["trans_hoverflap"].stopAt(0.3); + //mesh.sequences["trans_hoverflap"].start(); + Bird.model.sequences[Bird.currentseq].fadeout(0.2); + Bird.model.sequences["attack_trans"].fadein(0.2); + Bird.model.sequences["attack_trans"].stopTime=ofGetElapsedTimef()+0.6; + Bird.model.sequences["attack"].startAt(0.6); + Bird.currentseq="attack"; + } + break; + */ + /* + case 'y': + light.setPosition(light.getX(),light.getY()-100,light.getZ()); + printf("light at %f,%f,%f\n",light.getX(),light.getY(),light.getZ()); + break; + case 'n': + light.setPosition(light.getX(),light.getY()+100,light.getZ()); + printf("light at %f,%f,%f\n",light.getX(),light.getY(),light.getZ()); + break; + case 'g': + light.setPosition(light.getX()-100,light.getY(),light.getZ()); + printf("light at %f,%f,%f\n",light.getX(),light.getY(),light.getZ()); + break; + case 'j': + light.setPosition(light.getX()+100,light.getY(),light.getZ()); + printf("light at %f,%f,%f\n",light.getX(),light.getY(),light.getZ()); + break; + case 'u': + light.setPosition(light.getX(),light.getY(),light.getZ()+100); + printf("light at %f,%f,%f\n",light.getX(),light.getY(),light.getZ()); + break; + case 'b': + light.setPosition(light.getX(),light.getY(),light.getZ()-100); + printf("light at %f,%f,%f\n",light.getX(),light.getY(),light.getZ()); + break; + */ + case 'b': + if (!drawingborder) { + border.clear(); + drawingborder=true; + } + else drawingborder=false; + break; + case ' ': + ofSaveFrame(); + printf("[%8.2f] saved an image\n",ofGetElapsedTimef()); + break; + /* + case '>': + gameState=(gameState+1)%4; + gameStart=ofGetElapsedTimef(); + break; + + */ + } +} + +//-------------------------------------------------------------- +void testApp::keyReleased(int key){ + +} + +//-------------------------------------------------------------- +void testApp::mouseMoved(int x, int y ){ + +} + +//-------------------------------------------------------------- +void testApp::mouseDragged(int x, int y, int button){ + +} + +//-------------------------------------------------------------- +void testApp::mousePressed(int x, int y, int button){ + +} + +//-------------------------------------------------------------- +void testApp::mouseReleased(int x, int y, int button){ + pos=ofVec2f(x,y); + ofVec2f sp=screen2plane(pos); + if (drawingborder) { + border.push_back(sp); + } + printf("ray:%i,%i hit plane:%f,%f,%f\n",x,y,sp.x,sp.y); +} + +//-------------------------------------------------------------- +void testApp::windowResized(int w, int h){ + +} + +//-------------------------------------------------------------- +void testApp::gotMessage(ofMessage msg){ + +} + +//-------------------------------------------------------------- +void testApp::dragEvent(ofDragInfo dragInfo){ + +} + +void testApp::loadSettings(string filename){ + if( !XML.loadFile(filename) ){ + printf("unable to load %s check data/ folder\n",filename.c_str()); + }else{ + cam_angle=ofToInt(XML.getAttribute("gauntlet","cam_angle","none",0)); + threshold=ofToInt(XML.getAttribute("gauntlet","threshold","none",0)); + diffchannel=ofToInt(XML.getAttribute("gauntlet","keyChannel","none",0)); + learningRate=ofToFloat(XML.getAttribute("gauntlet","learningRate","none",0)); + removeShadows=ofToInt(XML.getAttribute("gauntlet","remove_shadows","none",0))==1; + testmovie=XML.getAttribute("gauntlet","testmovie","camoutput.move",0); + if(XML.pushTag("bounds")) { + for (int i=0;i<XML.getNumTags("vertex");i++){ + border.push_back(ofVec2f(ofToFloat(XML.getAttribute("vertex","x","0",i)),ofToFloat(XML.getAttribute("vertex","y","0",i)))); + } + XML.popTag(); + } + printf("loaded %s\n",filename.c_str()); + } +} +//-------------------------------------------------------------- +void testApp::saveSettings(string filename){ + XML.setAttribute("gauntlet","cam_angle",ofToString(cam_angle),0); + XML.setAttribute("gauntlet","threshold",ofToString(threshold),0); + XML.setAttribute("gauntlet","keyChannel",ofToString(diffchannel),0); + XML.setAttribute("gauntlet","remove_shadows",ofToString(removeShadows),0); + if (XML.tagExists("bounds")) XML.removeTag("bounds"); + XML.addTag("bounds"); + if(XML.pushTag("bounds")) { + for (int i=0;i<border.size();i++){ + XML.addTag("vertex"); + XML.setAttribute("vertex","x",ofToString(border[i].x),i); + XML.setAttribute("vertex","y",ofToString(border[i].y),i); + } + XML.popTag(); + } + XML.saveFile(filename); + printf("saved %s\n",filename.c_str()); +} |
