2014年03月29日

openFrameworksでとりあえずプロジェクションマッピング(実装編②)の続き

プログラムの統合、マッピングのテスト編

2014.4.4 追記&エラー修正



前回までの投稿でほとんど必要だと思われる部分が出来上がったので
とりあえずそれらを統合した。

使用addon
ofxOpenCv, ofxMSAInteractiveObject, ofxQuadWarp

ProjectionMapping
testApp.h

#pragma once
 
#include "ofMain.h"
#include "ofxQuadWarp.h"
 
class testApp : public ofBaseApp{
 
public:
    void setup();
    void update();
    void draw();
 
    void keyPressed(int key);
    void keyReleased(int key);
    void mouseMoved(int x, int y );
    void mouseDragged(int x, int y, int button);
    void mousePressed(int x, int y, int button);
    void mouseReleased(int x, int y, int button);
    void windowResized(int w, int h);
    void dragEvent(ofDragInfo dragInfo);
    void gotMessage(ofMessage msg);
 
    bool display;
    bool drawLine;
    ofImage apple;
 
    ofImage kariImage;
    vector img;
 
    vector warper;
    vector fbo;
 
    vector lx;
    vector ly;
    vector ww;
    vector hh;
    int mouseCount;
 
};


testApp.cpp

#include "testApp.h"
 
//--------------------------------------------------------------
void testApp::setup(){
    ofBackground(255, 255, 255);
    ofSetFrameRate( 60 );
    ofSetVerticalSync( true );
    ofEnableSmoothing();
 
    display = false;
    drawLine = true;
    apple.loadImage("apple.jpg");
}
 
//--------------------------------------------------------------
void testApp::update(){
    if(ofGetFrameNum()){
        return;
    } 
}
 
//--------------------------------------------------------------
void testApp::draw(){
    //この中にマッピングされる側のコードを書く
    ofBackground(255);
    ofSetColor(ofRandom(255), ofRandom(255), ofRandom(255));
    ofRect(30, 30, 200, 200);
 
    for(int i=0; i<200; i++){
        int r = ofRandom(10);
        ofEllipse(ofRandom(250, 450), ofRandom(30, 230), r, r);
    }
 
    ofSetColor(255, 255, 255);
    apple.draw(300, 300);
 
    //ここまで
    ofSetColor(100);
    ofNoFill();
 
    for (int i=0; i<img.size(); i++) {
        img[i].grabScreen(lx[i], ly[i], ww[i], hh[i]);
        if(drawLine){
            ofRect(lx[i], ly[i], ww[i], hh[i]);
        }
    }
 
    ofSetColor(255, 255, 255);
    ofFill();
 
    if (display) {
        ofBackground(0, 0, 0);
 
        for (int i=0; i<img.size(); i++) {
            fbo[i].begin();{
                img[i].draw(0, 0);
            }
            fbo[i].end();
 
            ofMatrix4x4 mat = warper[i].getMatrix();
 
            glPushMatrix();
            glMultMatrixf(mat.getPtr());
            {
                fbo[i].draw(0, 0);
            }
            glPopMatrix();
 
            ofSetColor(100, 100, 100);
            ofSetLineWidth(2);
            warper[i].draw();
 
            ofSetColor(255);
 
        }
    }
 
}
 
//--------------------------------------------------------------
void testApp::keyPressed(int key){
    if( key == 'a' ){
        if (display) {
            display = false;
        }else{
            display = true;
        }
 
    }
 
    if( key == 's' ){
        for (int i=0; i<img.size(); i++) {
            warper[i].toggleShow();
        }
 
        if (drawLine) {
            drawLine = false;
        }else{
            drawLine = true;
        }
    }
 
    if (key == 'f')
    {
        ofToggleFullscreen();
    }
 
}
 
//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button){
    if (!display) {
        if (mouseCount % 3 == 0) {
            lx.push_back(mouseX);
            ly.push_back(mouseY);
            ww.push_back(0);
            hh.push_back(0);
        }else if(mouseCount % 3 == 1){
            ww[mouseCount/3] = mouseX - lx[mouseCount/3];
            if (mouseX - lx[mouseCount/3] < 0) {
                lx[mouseCount/3] += ww[mouseCount/3];
                ww[mouseCount/3] *= -1;
            }
        }else{
            hh[mouseCount/3] = mouseY - ly[mouseCount/3];
            if (mouseY - ly[mouseCount/3] < 0) {
                ly[mouseCount/3] += hh[mouseCount/3];
                hh[mouseCount/3] *= -1;
            }
 
            kariImage.grabScreen(lx[mouseCount/3], ly[mouseCount/3], ww[mouseCount/3], hh[mouseCount/3]);
            img.push_back(kariImage);
 
            ofxQuadWarp kariWarper;
            warper.push_back(kariWarper);
 
            ofFbo kariFbo;
            fbo.push_back(kariFbo);
            fbo[mouseCount/3].allocate(ww[mouseCount/3], hh[mouseCount/3]);
            warper[mouseCount/3].setSourceRect(ofRectangle(0, 0, ww[mouseCount/3], hh[mouseCount/3]));
            warper[mouseCount/3].setTopLeftCornerPosition(ofPoint(lx[mouseCount/3], ly[mouseCount/3]));
            warper[mouseCount/3].setTopRightCornerPosition(ofPoint(lx[mouseCount/3] + ww[mouseCount/3], ly[mouseCount/3]));
            warper[mouseCount/3].setBottomLeftCornerPosition(ofPoint(lx[mouseCount/3], ly[mouseCount/3] + hh[mouseCount/3]));
            warper[mouseCount/3].setBottomRightCornerPosition(ofPoint(lx[mouseCount/3] + ww[mouseCount/3], ly[mouseCount/3] + hh[mouseCount/3]));
            warper[mouseCount/3].setup();
 
            for (int i=0; i<img.size(); i++) {
                fbo[i].allocate(ww[i], hh[i]);
 
                warper[i].setSourceRect(ofRectangle(0, 0, ww[i], hh[i]));
                warper[i].setTopLeftCornerPosition(ofPoint(lx[i], ly[i]));
                warper[i].setTopRightCornerPosition(ofPoint(lx[i] + ww[i], ly[i]));
                warper[i].setBottomLeftCornerPosition(ofPoint(lx[i], ly[i] + hh[i]));
                warper[i].setBottomRightCornerPosition(ofPoint(lx[i] + ww[i], ly[i] + hh[i]));
                warper[i].setup();
            }
 
        }
        mouseCount++;
    }
 
}


操作方法
aキーで画面きりかえ
sキーで枠線を消す
fキーでフルスクリーン

画像の切り取りは前回と同じで
一回目基準の位置を決定
二回目基準からの幅を決定

三回目基準からの高さを決定、新しい画面を作る

 
見つけたけど修正してない(できてない)問題点

①新しく画像を追加するとマッピング画面でキャリブレーションした側の
設定が全てリセットされてやり直しになる
→いろいろ頑張ってみたものの新しい画像を追加する時に今までの画像を
初期化しないとそれ以降画像を触れなくなったので毎回初期化するようにした。

 
②作った画像を消せない
→動的配列なので.clear()などで消すことを想定してたが一度消してから次の画像を
作成しようとするとメモリ?らへんでエラーが起きる。現状原因不明

 
③時々実行しキャリブレーション画面に切り替えるとよくわからないところで
エラーがでる。現状原因不明
 
たまたまこの記事をみてくれた方で心当たりがあれば教えてください。

実行するとこんな感じ



てきとーにマッピングしてみた



今は四角の画像しか扱えないけど画像処理頑張れば丸くマスクかけたり
ライブラリをいじれば三角とかできると思う。

今回のこれはソフトウェアに頼らずoFのみでプロジェクションマッピング
っぽいことを実現することが目標だったから、ライブラリは利用したけど
最低限の形にはなった。


>>追記1
ブログ投稿後全く違うアプローチでoFを勉強していたらどうも動的配列を
扱う際はポインタを使った方がよさげなことが判明したので
ポインタを使う感じで書き直したらいろいろうまくいって改善された。
①、②については修正できた。
③のエラーも起こらなくなってる気がする。
しかし、こんなのでつまづいているなんて自分のプログラムの書けなさを
インターネットにのせて世界に発信してるようなものだな。
参考:http://yoppa.org/ma2_10/2032.html

>>追記2
ブログを書いたあとに知った記事ですがこんなのあった。
ガチでギークな女優、池澤あやかのプロジェクションマッピングがすごい
使ってるライブラリ一緒なのでMacPeople買ったらかわいい女の子が
詳しく解説してくれたりしてるのかな???



以下、ソース

testApp.h

#pragma once
 
#include "ofMain.h"
#include "ofxQuadWarp.h"
 
class testApp : public ofBaseApp{
 
public:
    void setup();
    void update();
    void draw();
 
    void keyPressed(int key);
    void keyReleased(int key);
    void mouseMoved(int x, int y );
    void mouseDragged(int x, int y, int button);
    void mousePressed(int x, int y, int button);
    void mouseReleased(int x, int y, int button);
    void windowResized(int w, int h);
    void dragEvent(ofDragInfo dragInfo);
    void gotMessage(ofMessage msg);
 
    bool display;
    bool drawLine;
    ofImage apple;
 
    vector<ofImage *> img;
    vector<ofFbo *> fbo;
    vector<ofxQuadWarp *> warper;
 
    vector<int> lx;
    vector<int> ly;
    vector<int> ww;
    vector<int> hh;
    int mouseCount;
 
 
};




testApp.cpp

#include "testApp.h"
 
//--------------------------------------------------------------
void testApp::setup(){
    ofBackground(255, 255, 255);
    ofSetFrameRate( 60 );
    ofSetVerticalSync( true );
    ofEnableSmoothing();
 
    display = false;
    drawLine = true;
    apple.loadImage("apple.jpg");
 
 
}
 
//--------------------------------------------------------------
void testApp::update(){
 
    if(ofGetFrameNum()){
        return;
    }
 
 
 
}
 
//--------------------------------------------------------------
void testApp::draw(){
    //この中にマッピングされる側のコードを書く
    ofBackground(255);
    ofSetColor(ofRandom(255), ofRandom(255), ofRandom(255));
    ofRect(30, 30, 200, 200);
 
    for(int i=0; i<200; i++){
        int r = ofRandom(10);
        ofEllipse(ofRandom(250, 650), ofRandom(30, 230), r, r);
    }
 
    ofSetColor(255, 255, 255);
    apple.draw(300, 250);
 
 
    //ここまで
    ofSetColor(100);
    ofNoFill();
 
    for (int i=0; i<img.size(); i++) {
        img[i]->grabScreen(lx[i], ly[i], ww[i], hh[i]);
        if(drawLine){
            ofRect(lx[i], ly[i], ww[i], hh[i]);
        }
    }
 
    ofSetColor(255, 255, 255);
    ofFill();
 
    if (display) {
        ofBackground(0, 0, 0);
 
        for (int i=0; i<img.size(); i++) {
 
            fbo[i]->begin();{
                img[i]->draw(0, 0);
            }
            fbo[i]->end();
 
            ofMatrix4x4 mat = warper[i]->getMatrix();
 
            glPushMatrix();
            glMultMatrixf(mat.getPtr());
            {
                fbo[i]->draw(0, 0);
            }
            glPopMatrix();
 
            ofSetColor(100, 100, 100);
            ofSetLineWidth(2);
            warper[i]->draw();
 
            ofSetColor(255);
 
        }
    }
 
}
 
//--------------------------------------------------------------
void testApp::keyPressed(int key){
    if( key == 'a' ){
        if (display) {
            display = false;
        }else{
            display = true;
        }
 
    }
 
    if( key == 's' ){
        for (int i=0; i<img.size(); i++) {
            warper[i]->toggleShow();
        }
 
        if (drawLine) {
            drawLine = false;
        }else{
            drawLine = true;
        }
    }
 
    if (key == 'f')
    {
        ofToggleFullscreen();
    }
 
    if(key == 'd'){
        lx.pop_back();
        ly.pop_back();
        ww.pop_back();
        hh.pop_back();
        delete img[img.size()-1];
        img.pop_back();
        delete fbo[fbo.size()-1];
        fbo.pop_back();
        delete warper[warper.size()-1];
        warper.pop_back();
 
        mouseCount -= 3;
    }
 
    if (key == 'D') {
        lx.clear();
        ly.clear();
        ww.clear();
        hh.clear();
        for (int i=0; i<img.size(); i++) {
            delete img[i];
            delete fbo[i];
            delete warper[i];
        }
        img.clear();
        fbo.clear();
        warper.clear();
 
        mouseCount = 0;
    }
 
}
 
 
//--------------------------------------------------------------
void testApp::mousePressed(int x, int y, int button){
    if (!display) {
        if (mouseCount % 3 == 0) {
            lx.push_back(mouseX);
            ly.push_back(mouseY);
            ww.push_back(0);
            hh.push_back(0);
        }else if(mouseCount % 3 == 1){
            ww[mouseCount/3] = mouseX - lx[mouseCount/3];
            if (mouseX - lx[mouseCount/3] < 0) {
                lx[mouseCount/3] += ww[mouseCount/3];
                ww[mouseCount/3] *= -1;
            }
        }else{
            hh[mouseCount/3] = mouseY - ly[mouseCount/3];
            if (mouseY - ly[mouseCount/3] < 0) {
                ly[mouseCount/3] += hh[mouseCount/3];
                hh[mouseCount/3] *= -1;
            }
 
            img.push_back(new ofImage);
            img[mouseCount/3]->grabScreen(lx[mouseCount/3], ly[mouseCount/3], ww[mouseCount/3], hh[mouseCount/3]);
 
 
            ofxQuadWarp kariWarper;
            warper.push_back(new ofxQuadWarp);
 
            ofFbo kariFbo;
            fbo.push_back(new ofFbo);
 
            fbo[mouseCount/3]->allocate(ww[mouseCount/3], hh[mouseCount/3]);
            warper[mouseCount/3]->setSourceRect(ofRectangle(0, 0, ww[mouseCount/3], hh[mouseCount/3]));
            warper[mouseCount/3]->setTopLeftCornerPosition(ofPoint(lx[mouseCount/3], ly[mouseCount/3]));
            warper[mouseCount/3]->setTopRightCornerPosition(ofPoint(lx[mouseCount/3] + ww[mouseCount/3], ly[mouseCount/3]));
            warper[mouseCount/3]->setBottomLeftCornerPosition(ofPoint(lx[mouseCount/3], ly[mouseCount/3] + hh[mouseCount/3]));
            warper[mouseCount/3]->setBottomRightCornerPosition(ofPoint(lx[mouseCount/3] + ww[mouseCount/3], ly[mouseCount/3] + hh[mouseCount/3]));
            warper[mouseCount/3]->setup();
 
        }
        mouseCount++;
    }
 
 
}





動作環境
Xcode 5.0
openFrameworks 8.0
OSX 10.8.5


コメントを残す

© Sako.log All Rights Reserved.