Pharoで3D表示

これはSmalltalk Advent Calendar 2014の12/23の記事です。
以前からPharoで3D表示させたいと考えていた。NativeBoost経由でOpenGLを使うNBOpenGLを試してみたのだが、どうやらメンテされていないらしくうまく動作しない。
そんなところ、第67回Smalltalk勉強会でRoassalが取り上げられた。あいにく仕事で参加できなかったのだが、プレゼン資料でRoassal3dについても紹介されていたので、遊んでみることにした。

Roassal3dの導入

MetacelloConfigurationBrowser open.

上記をWorkspaceでDo itしてConfiguration Browserを起動する。一覧からRoassal3dを選んでInstall stable versionをクリックすると自動的にRoassal3dがインストールされる。

サンプルの実行

Roassal3dの機能をひととおり試してみるには以下をWorkspaceでDo itする。

R3RoassalExample new open.

いろんなアイコンが並んでいるのでマウスで左クリックするとそれぞれのデモウィンドウが現れる。右クリックをするとBrowserが現れ、対応するメソッドが表示される。
デモウィンドウの操作はキーおよびマウスで行う。キー操作では、Wは前進、Sは後退、Aは左移動、Dは右移動、Cが下移動、スペースが上移動できる。マウスではドラッグにより向きを変えることができる。
デモの中にはアニメーションを表示したり、マウスの動きに反応するものがある。

3Dビューの作成

R3Viewのインスタンスに対して、R3Elementのインスタンスを追加することで3Dビューを作成する。
R3Elementには形や位置、向きなどの様々な属性がある。立方体や球体など一般的な物体は、R3Elementを直接生成せず、R3Shapeの該当するサブクラスを経由して生成する。
以下は最も簡単なサンプルで3Dビューの中心に立方体を置くものである。

| view |
view := R3View new.
view add: R3CubeShape new element.
view open.

上記で生成した3Dビューをinspectしてelementsを調べると2個の要素がある一方は生成した立方体で、もう一方は照明である。
立方体の位置を変えるには、R3Vectorオブジェクトを引数としてposition:メッセージを送れば良い。

view elements last position: (R3Vector x: -1 y: -1 z: 0); signalUpdate

先ほどのコードに続けて上記をDo itすれば、立方体は中央から左下に移動する。
position:を送っただけでは3Dビューに変化は現れないので、signalUpdateを送って3Dビューを更新する。

アニメーション

3Dビュー上の物体を動かす手段としてアニメーションがある。R3ViewのインスタンスにR3Animationのインスタンスをアニメーションとして登録すると、3Dビューの更新にあわせてアニメーションが動作する。R3AnimationはR3Elementに作用して位置や向きを変えることができる。
以下のコードをDo itすると、立方体が中央から左下に移動する。

| view element animation |
view := R3View new.
element := R3CubeShape new.
view add: element element.
animation := R3LinearMove new on: element by: (R3Vector3 x: -1 y: -1 z: 0).
view addAnimation: animation.
view open.

複数のアニメーションを連結させて、連続したアニメーションを作ることもできる。
以下のコードでは、立方体が4隅を連続して移動する。

| view element a1 a2 a3 a4 |
view := R3View new.
element := R3CubeShape new element.
view add: element.
a1 := R3LinearMove new on: element by: (R3Vector3 x: -1 y: -1 z: 0).
a2 := R3LinearMove new on: element by: (R3Vector3 x: 1 y: -1 z: 0).
a3 := R3LinearMove new on: element by: (R3Vector3 x: 1 y: 1 z: 0).
a4 := R3LinearMove new on: element by: (R3Vector3 x: -1 y: 1 z: 0).
a1 followedBy: a2.
a2 followedBy: a3.
a3 followedBy: a4.
a4 followedBy: a1.
view addAnimation: a1.
view open.

インタラクション

今までの例では3Dビューは固定されたカメラからの画像しか得ることができなかったが、冒頭のサンプルのようにキーボードやマウスを用いてカメラの位置を変えることができる。
そのためには以下のコードを追加すればよい。

view addInteraction: R3MKControl.

以上概観したように、Roassal3dはPharo上で簡単に3D表示することのできる優れたパッケージである。
この記事では一つの物体のみ操作したが、少ない労力で多数の物体の操作を行うこともできる。
Roassal3dに関する情報はObject Profileのwebサイトから得ることができる。