[Polycode] コードで作成した画像を表示する

LINEで送る
Pocket

さて、今回はちょっと飛躍してコード上で各ピクセルのデータを作成して表示する方法をご紹介します。

通常であれば、Imageのコンストラクタにファイル名を追加すれば指定された画像が表示されるのですが、例えばKinectの映像や動画などを表示させたい場合はファイル名の指定ではできませんのでこの方法を使います。

早速サンプルコード。これをPolycodeTemplateAppクラスのコンストラクタに記述して下さい。
このサンプルでは、640x480pxでRGBAの紫の画像を表示させます。

	// Write your code here!
    Screen* screen = new Screen();
    // 表示させる画像のピクセルデータを作成します。
    char* pixels = (char*)malloc(640*480*4*sizeof(char));
    for(int y = 0; y < 480; y++)
    {
        for(int x = 0; x < 640; x++)
        {
            int index = (x + y * 640) * 4;
            pixels[index] = 255;
            pixels[index+1] = 0;
            pixels[index+2] = 255;
            pixels[index+3] = 255;
        }
    }
    
    Image* image = new Image(pixels, 640, 480);
    
    ScreenImage* screenImage = new ScreenImage(image);
    screenImage->setPosition(0, 0, 0);
    screen->addChild(screenImage);
    free(pixels);

Imageのコンストラクタの引数には、charのポインタを設定させる事ができます。
この場合、種類は[char型の画像データ, 幅, 高さ] を指定します。

    Image* image = new Image(pixels, 640, 480);

後の流れは通常の画像表示と変わりません。

で、以下の部分は640x480pxで、RGBAの紫の画像データを生成しています。
この流れは画像にエフェクトをかけたりする場合(※Shaderの場合はまた別の方法ですけどね)や画像のデータを解析する時に使ったりするので覚えておくと良いです。

    char* pixels = (char*)malloc(640*480*4*sizeof(char));
    for(int y = 0; y < 480; y++)
    {
        for(int x = 0; x < 640; x++)
        {
            int index = (x + y * 640) * 4;
            pixels[index] = 255;       // R
            pixels[index+1] = 0;      // G
            pixels[index+2] = 255;  // B
            pixels[index+3] = 255;  // A
        }
    }

この処理を延々と繰り返す事で画像をリアルタイムに変化させる事が可能になりました。
次回は、OpenNIで拾ったデータを表示させてみましょう。

Polycode – 2D空間での画像表示

LINEで送る
Pocket

今度はPolycodeの2D空間上で画像を表示させてみましょう。
今まで同様、PolycodeTemplateApp.cppのコンストラクタに下記のコードを追加します。
追加するコード:

    core = new CocoaCore(view, 640,480,false,0,60);	  
	CoreServices::getInstance()->getResourceManager()->addArchive("default.pak");
	CoreServices::getInstance()->getResourceManager()->addDirResource("default");

	// Write your code here!
    // 2Dの場合はScreenを使います。
    Screen* screen = new Screen();
    Image* image = new Image("../Resources/icon.png");
    ScreenImage* screenImage = new ScreenImage(image);
    screenImage->setPosition(100, 100, 0);
    screen->addChild(screenImage);
}

実行結果がこれ。画面にアイコンが表示されています。
polycode_2dimage

Polycodeでは、2D空間の場合はScreen、3D空間の場合はSceneというクラスのインスタンスをつかって空間を表します。
今回は2D空間に画像を表示させるサンプルなので、Sceenを使っています。

次に、画像を表示させるまでの方法ですが、紛らわしいですがImageクラスとScreenImageクラスを使っています。
2つの違いとしては、

Imageクラス
メモリ上に存在する、ビットマップデータ
ScreenImageクラス
2D空間上に画像を表示させる表示オブジェクト

といったところです。
ActionScriptになじんでいる方であれば、BitmapDataクラスとBitmapクラスの違い、と理解すると良いと思います。

表示オブジェクトの座標は、setPositionメソッドを使って設定します。引数はx, y, z座標の順番になっています。
2D空間の場合、z座標を0以外にすると表示されないので気をつけましょう。

ImageクラスにはsetPixelというこれまたActionScriptに慣れた人には分かりやすいメソッドがあり、これを使う事でピクセル毎の操作ができるようになります。
Imageクラスのコンストラクタに画像ファイルパスを指定すると、パスにある画像を読み込みます。ただし、今現在はpng形式の画像にしか対応していない様です。

ScreenImageクラスのコンストラクタにImageクラスのインスタンスを入れる事で、Imageを表示させる事ができるようになります。

僕はMacでコードを書いているのですが、表示させている画像はXCodeのプロジェクトにicon.pngという画像を追加していますが、ビルド後の実行ファイルと画像などの格納場所との位置関係を考慮し、”../Resources/”とパスを追加しています。
VisualStudioの場合はこういったことはしなくてよかったはず。

最後、表示させるにはscreenオブジェクトのaddChildメソッドを使って表示オブジェクトに表示させます。これもActionScript使いにはなじみが強いですね。

しばらくはつまらない基礎編が多いですが、いきなりOpenNIで表示、みたいな事をやってもわけがわからなくなるので順番に書く事にします。

Polycode – コードを書き始める。

LINEで送る
Pocket

polycode_header

それではコードを書き始めましょう。
Template/Xcode Template
以下のプロジェクトファイルを開きます。今後はこのテンプレートを使う事になりますので、Xcode Templateをコピーしておく事をお勧めします。

プロジェクトを開くと、様々なファイルがありますが、
PolycodeTemplateApp.mm、PolycodeTemplateApp.h
にコードを書きます。
Openframeworksでいう、testAppクラスに相当します。

まずはPolycodeTemplateApp.mm全体をみてみましょう。

//
// Polycode template. Write your code here.
// 

#include "PolycodeTemplateApp.h"


PolycodeTemplateApp::PolycodeTemplateApp(PolycodeView *view) {
    core = new CocoaCore(view, 640,480,false,0,60);	  
	CoreServices::getInstance()->getResourceManager()->addArchive("default.pak");
	CoreServices::getInstance()->getResourceManager()->addDirResource("default");

	// Write your code here!
}

PolycodeTemplateApp::~PolycodeTemplateApp() {
    
}

bool PolycodeTemplateApp::Update() {
    return core->Update();
}

コードをみてわかるように、このクラスは3つのメソッドを持っています。

コンストラクタ(PolycodeTemplateApp::PolycodeTemplateApp)
は起動時に一度呼ばれ、初期設定などを受け持ちます。
Openframeworksでいう、setupメソッドの役割です。

デストラクタ(PolycodeTemplateApp::~PolycodeTemplateApp)
はアプリケーションの後処理に使われます。

updateメソッド(PolycodeTemplateApp::Update)
は定期的に呼ばれるので、アニメーションさせたい場合に使います。
Openframeworksでいうと、updateとdrawメソッドをかねています。

では、Polycodeのサイトにある、テキストを表示させるサンプルを参考にプログラムを書いてみましょう。
http://polycode.org/learning/text_basics

2D空間に「Hello, Polycode!」という文字を表示させます。
コンストラクタに下記のコードを追加します。(// Write your code here!ははじめから書いています。)

// Write your code here!
    Screen* screen = new Screen();
    ScreenLabel* label = new ScreenLabel("Hello, Polycode!", 32);
    screen->addChild(label);

まず、

  1. Screenを生成し、オブジェクトを表示させるためのインスタンスを準備します。
  2. ScreenLabelを生成し、表示させたい文字列と文字のサイズを指定します。
  3. addChildメソッドを使って画面に文字列を表示させるようにしましょう。これはActionScript3.0に近い書き方ですね。

これを追加して実行すると、このようなWindowが表示されます。

実行結果

実行結果

簡単ですね!
それではこれからはアニメーションさせたり画像を表示させたりしましょう。

Polycode

LINEで送る
Pocket

polycode_header
僕の中でここ最近気になっているPolycodeというC++/Luaのframeworkが熱い。今後がすごく楽しみなので記事にしてみます。

Polycode(http://polycode.org/)とは、Ivan Safrin(http://www.ivansafrin.com/)という人が作ったOpenframeworksに近いWin/Mac対応のcreativeなcodeを書くためのframework。

物理エンジンも使えるようになっており、2DではBox2D、3DではBullet Physicsを採用しているようです。

Openframeworksと比べて何が良いかというと、
・3Dに関する機能がOpenframeworksよりも充実している
・OpenALのように位置を指定してサウンドをならす事もできる
・shaderを簡単に組み込む事ができるなどエフェクトにも対応している
・スケルトンの表示やアニメーションにも対応しており、3Dソフトから書き出したデータをアニメーションさせて表示させる事もできる

という違いがあります。

2011年6月時点ではAlphaリリースなので不安定らしいですが、かなり期待できると思います。

現在はLinuxやiOSには対応していないですが、Linuxは対応中のようです。iOSについては、ソースコードをみる限りそれらしいクラスがあるのでこちらも近々対応するのではないかと思っています。

これからもPolycodeの情報を書いていこうと思います。