Projection Mapping」カテゴリーアーカイブ

Processingを用いたプロジェクションマッピング

以前にもブログで紹介しているルービックキューブへのプロジェクションマッピングについて、またまたですが異なるアプローチで試してみました。

今回は Processing を利用しました。(実は今までの中で最もシンプル)

プロジェクションマッピングでの課題はキャリブレーション(マッピングのための調整)ですが、Processing には「keystone」という射影変換を実現するライブラリが公開されているとのことで、こちらを最大限に活用させていただきました。

ライブラリの追加方法です。
1. メニューから次の項目を選択する。 Sketch > Import Library > Add Library
2. 「keystone」を選択してインストールする

先に作成したデモ映像を載せておきます。

投影環境はこんな感じです。
IMG_1201

コードについては、簡易な説明にしておきます。
「keystone」ライブラリに関する主要なインスタンスは以下になります。

projectionMappingCube.pde

Keystone ks;	// Keystone本体(画面全体を指す)

 

SurfaceBase.pde

class SurfaceBase 
{
  CornerPinSurface surface;	// 射影平面
  PGraphics offscreen;	// 射影平面内部のグラフィックス

  SurfaceBase() {
    
    surface = ks.createCornerPinSurface(600, 600, 60);
    offscreen = createGraphics(600, 600, P3D);
    
    // 略
  }

  // 略
}

 

あらかじめ割り当てたキーを押下することで、投影の表示を切り替えを行うのに加え、キャリブレーションに関する処理についても行っています。

projectionMappingCube.pde

// 起動時に呼ばれる
void setup() {
  // 略
}

// 描画更新時に呼ばれる
void draw() {
  // 略
}

// キー押下時に呼ばれる
void keyPressed() {
  switch(key) {
  case '0':
  case '1':
  case '2':

    // 略

    break;

  case 'c':
    // キャリブレーション(CornerPinSurface の各頂点をマウスで設定できる)
    ks.toggleCalibration();
    break;

  case 'l':
    // 前回保存したキャリブレーション情報をロード
    ks.load();
    break;

  case 's':
    // キャリブレーション結果を保存
    ks.save();
    break;
  }
}

 

キャリブレーションする前は、実行した画面の左上に接した正方形が表示されることになりますが、キー’c’を押下することで形状を調整できるようになります。調整が完了したら、再度キー’c’を押下することでキャリブレーション状態から抜けることができます。
キー’s’を押下すると、同一ディレクトリに「keystone.xml」が作成され、調整した状態が保存されます。これで、次回起動したときに、キー’l’を押下することで前回調整した状態に復元されます。

デモ映像の抜粋版のコードを Github にアップしました。
https://github.com/JunichiMinamino/projectionMappingCube

今回は比較的負荷が少ない処理の内容にとどめたので、Processing で作成するのに適しているかと思います。より負荷の高い処理を行いたい場合は openFrameworks を利用する方が良いかと思います。
今回はキャリブレーションについてもがんばってみたこともあり、少しコツがわかってきた感じがします。またの機会に再度oFでも試してみようと思います。

逆プロジェクションマッピング

前回に引き続き、プロジェクションマッピングを試してみました。対象は前回と同じルービックキューブですが、今回は実物への投影を試してみました。

単に投影させるだけではおもしろくない、ということで、openFrameworks のAddonにある、ofxBullet という3Dの物理エンジンを用いていくつかギミックを入れてみることにしました。

投影環境はこんな感じです。

IMG_2091

作成した映像はこちら。

実際に投影して改めて認識したことですが、、プロジェクションマッピングにおいてはキャリブレーション(マッピングのための調整)のための施策や考慮がかなり重要であるようです。
今回の場合は斜めから投影していることもあり、投影画像全体を変形して出力させるべきであったかと思いましたが、その方法が見つからなかったので、残念ながら次回までの課題となりました。実際、上面は全然合っていませんが、今回は見逃していただくということで。。

以下は映像での実現方法について説明します。映像では以下の項目の内容を試しています。

1. 投影 色変化
2. ブロックが下に落ちる(全体)
3. ブロックが下に落ちる(1つずつ)
4. ブロックの分解
5. 逆投影

27個の立方体のブロックを並べることでルービックキューブを実現しています。

最初に各ブロックの生成について説明しておきます。ブロックはvector配列で管理しています。

vector<ofxBulletBaseShape *> shapes;

以下の処理でブロックを1つ生成しています。

void testApp::addShapeBox(int x, int y, int z, float mass, float size)
{
	shapes.push_back(new ofxBulletBox());
	int i = shapes.size() - 1;

	ofQuaternion qt(0.0, 1.0, 0.0, 1.0);
	((ofxBulletBox *)shapes[i])->create(world.world, ofVec3f(x, y, z), qt, mass, size, size, size);

	shapes[i]->setActivationState(DISABLE_DEACTIVATION);
	shapes[i]->add();
}

ポイントは mass の設定で、mass = 0.0; と設定することで、重力に影響しない固定のブロックになります。また、重力に影響する可変のブロックは mass = 1.0; で設定しています。
また、ofQuaternion を上記のように定義することで、Z軸を中心に45度回転したブロックを設置することができます。

ブロックの消去は以下の処理で行います。これでブロックの作成/消去が自在に行えます。

void testApp::deleteShape(int index)
{
	delete shapes[index];
	shapes[index] = NULL;
	shapes.erase( shapes.begin() + index );
}

また、映像では最初に透明の床を用意してあり、床の上にルービックキューブ状のブロックを置き、適切なタイミングで床の作成/消去を設定しています。

「2」では、全てのブロックを重力に影響する可変に設定して、床を消去することで実現しています。
「3」では、あらかじめ床を消去しておき、全てのブロックを重力に影響しない固定に設定して、ブロックを1つずつ可変な状態に生成し直すことを行っています。

「4」では、各ブロックに対して、瞬間的に力を加えることではじき飛ばされるようなアクションを実現しています。

void testApp::addShapeBox(int index)
{
	shapes[index]->activate();
	shapes[index]->applyForce(ofVec3f(100, -100, 100), ofVec3f(3, -50, 3));
}

最後の「5」ですが、可変のブロックの上から非常に重い球を落として、それに合わせて実物のボールを置くという、タイトルにもある「逆プロジェクションマッピング」というのを試してみようかと思いましたが、かなりズレてしまってますね。。まあ今回はこれでご勘弁ください。

個人的にはキャリブレーションの課題が心残りですが、それが解決すれば、いろいろおもしろいことが展開していけそうに思いました。

プロジェクションマッピング テスト

ちまたで流行っているプロジェクションマッピングを試してみました。
東京駅など建設物に投影する本格的なものは、After Effects などグラフィックスソフトを使うのが一般的かと思いますが、私はそちらの方はやったことがないので、プログラムにてできることをやってみました。

まずは機器を準備ということで、プロジェクターは QUMI Q5 を購入しました。
なんと、ここまで小型化されてかつ高性能なのには驚かされました。

IMG_1931

今回のテスト動画です。

比較的やりやすそうなターゲットとして、ルービックキューブへの投影を試してみました。
加えて、周辺からボール状の小さな物体をたくさん発生させて、ルービックキューブの投影と衝突させるという効果を出してみたいと思いました。

実際に着手していくと課題点もいくつか出てきました。
まず、ルービックキューブ実物を投影してみようとすると、ターゲットが小さいため直接投影させるには難しいと感じたので、ルービックキューブの写真を印刷したもので投影することにしました。
印刷したものに投影してみると、各面が平行四辺形でもないただの四角形なため、各面の9個のブロックの座標をマッピング画像に合わせることが非常に難しかったです。(四角形のベクトル計算から立ち戻りましたが、結局合っていないです。。)

プログラムは openFrameworks で実現しています。
AddOnは ofxQuadWarp と ofxBox2d を使用しました。
ルービックキューブの各面の作成は、ofxQuadWarp を3つ生成して、投影したプロジェクター画面に合わせて、あらかじめ座標を手動で調整しました。(つまり、キャリブレーションは手動で行いました。)
ルービックキューブの輪郭と降ってくるボール状の物体は ofxBox2d による物理エンジンを適用しています。

今回のテスト動画の演出については、Macにて割り当てたkeyを押して切り替えることでアクションを起こしています。
かつ、もう一方の手で持っていたiPhoneで撮影したため、ブレは気になるところですが、、何卒ご了承いただければと思います。