PR

JOGLの解説を3カ月にわたって長々と行ってきたのは,3Dのアプリケーションを作るためということもあります。

しかし,一番の理由は,2Dのアプリケーションに3Dを融合させた姿を紹介したかったからです。2Dのアプリケーションの表現力を3Dによって向上させてもらいたかったのです。

2Dと3Dの融合には二つの方法論があります。

  1. 3D空間の中に,2Dアプリケーションを取り入れる
  2. 2Dアプリケーションの中に,3Dの空間を取り入れる

1.の方法で代表的なのはウィンドウ・システムを3D化することです。

この方法を使用している代表的なウィンドウ・システムを次に示します。

  • Project Looking Glass(LG3D)
  • Windows Vista(Windows Aero)
  • Susie XGL
  • Mac OS X

いずれのウィンドウ・システムも見た目は2Dかもしれませんが,3D空間を扱うことができます。3Dの世界に置くことでウィンドウを3Dに配置することや,透明などの効果をふんだんに扱うことができます。

これらのウィンドウ・システムの大きな特徴は,個々のアプリケーションを意識しなくても,3Dの恩恵にあずかれることです。

3D化することで,透明や奥行きなどを使うことができます。

ウィンドウを半透明にすれば,裏側に隠れたウィンドウを見ることができます。また,奥行きを使うことでウィンドウの配置も工夫できます。例えば,LG3Dのようにスクリーンの端にウィンドウを立てておいたり,Windows Vistaのようにアプリケーションを切り替えるときに一覧表示することも可能です。

そのほかにも3Dを利用することで使いやすさを向上する術はいろいろとあります。

個々のアプリケーションは,何もしなくてもこのような利点の恩恵を受けることができます。アプリケーション開発者からすると,面倒な3Dの要素を考えなくても,普段と全く同じようにアプリケーションを作成できます。

この方法の欠点は,新しいがゆえの欠点です。

最近のウィンドウ・システムはOSと一体化されているものが多いので,3Dのウィンドウ・システムを使用するには,OSから入れ替えなくてはなりません。しかし,これは初心者からすればかなりハードルが高い作業ですね。未だにWindows 98を使用している人も多いのですから。

しかし,これらのウィンドウ・システムには,この欠点を上回るほどの魅力があります。どのウィンドウ・システムでもいいので,ぜひ一度試してみていただきたいと思います。

さて,もう一つの手法が,2Dアプリケーションの中に,3Dの空間を取り入れることです。これこそ,筆者がお勧めする方法です。

2Dのアプリケーションの見た目や使い方を向上させるために,ちょっとした3Dの要素を取り入れる。例えば,アニメーションとか,半透明であるとか,エンボス・ベベル・ドロップシャドウなどの効果とか。

これらの効果はもちろん2Dでも実現できます。

例えば,Windows XPのウィンドウの枠はベベルで装飾されています。よく見ると,上が明るく下が暗くなっており,右と左を比べると若干左側が明るくなっています。これは左上からライトが当たっていることを示しています。

しかし,3Dのように光がどこから当たっているかを計算しているわけではなく,あくまでも擬似的に描画しているにすぎません。

ここで示した例のように,今までも3Dの概念はある程度使われてきました。擬似的に行われてきたのは,3Dの描画のコストが高かったからです。

ところが,最近のCPUやGPUの性能向上,特にGPUの性能向上により,3Dの描画のコストは格段に下がっています。従来の3Dグラフィックスは,高性能で高価格のグラフィック・カードが必要でしたが,現在はそこそこのGPU,それこそチップセットに内蔵されているGPUでも十分に3Dを楽しめるようになっています。

こんな今こそ,3Dを取り入れるチャンスです。

ここで2Dアプリケーションに3Dを取り入れた例を二つご紹介しましょう。どちらのアプリケーションもサンプルとして作られたものですが,とても興味深いものです。

Aerith

Aerith
図1 Aerith
Aerithメインメニュー
図2 Aerithメインメニュー
Aerith写真表示
図3 Aerith写真表示

Aerithは今年のJavaOneの基調講演でデモされたアプリケーションです。JavaOneではGoogle Maps APIFlickr APIYahoo! Geocoding APIという三つのWeb APIを利用したMash Upアプリケーションとして紹介されました(Swingを使ってMash Upということで'S'Mash Upと呼ばれていました)。

Aerithは旅行記を作るためのアプリケーションで,地図をGoogle Mapsで表示し,そこにルートを重ねたり,写真やメモを表示できます。ここで使用している写真はFlickrから取得してきています。

地図とは別に,写真をスライドショーのように表示することもできます。

Aerithはjava.netでソースが公開されています。残念ながらバイナリ・パッケージはないのですが,Java Web Start版があるので試しに実行できます

それではJava Web Startで実行させてみましょう。起動にはJava SE 6が必要です。

起動するとスプラッシュ画面が表示され,Flickrのアカウントの入力画面に移ります。もし,ご自分のFlickrアカウントがあればそれを使っても構いません。JavaOneではromainguyというアカウント(SwingチームのRomain Guy氏のアカウント)を使っていました。

ちなみに図2,図3では筆者のFlickrアカウントを使用しています。

アカウントを入力すると,メインメニューに進みます。[View Photos]を選んでみましょう。すると,Flickrのアルバムが選択できます。アルバムを選択すると,写真が表示されます。

図3を見ればおわかりのように,写真は3D的に配置されます。矢印型のボタンをクリックすると,表示している写真が飛ぶように移動して入れ替わります。

もうおわかりだと思いますが,この部分はJOGLで記述されています。

イメージはポリゴンにテクスチャとして貼ってあります。ポリゴンを回転・移動させると,そこに貼られたイメージも一緒に変化します。

この部分はorg.progx.twinkle.ui.PictureViewerクラスのsetAndRenderメソッドで実現しています。

  private static void setAndRender(GL gl, 
                                   Renderable renderable,
                                   boolean antiAliased) {
    if (renderable == null) {
      return;
    }
         
    Point3f pos = renderable.getPosition();
    Point3i rot = renderable.getRotation();
    Point3f scale = renderable.getScale();
 
    gl.glPushMatrix();
    gl.glScalef(scale.x, scale.y, scale.z);
    gl.glTranslatef(pos.x, pos.y + 4.0f, pos.z);
    gl.glRotatef(rot.x, 1.0f, 0.0f, 0.0f);
    gl.glRotatef(rot.y, 0.0f, 1.0f, 0.0f);
    gl.glRotatef(rot.z, 0.0f, 0.0f, 1.0f);
        
    renderable.render(gl, antiAliased);
    gl.glPopMatrix();
  }

イメージが移動するアニメーションの軌跡はrenderable変数が保持しているので,そこから位置,拡大率,回転角度を取り出します。そして,それぞれGL#glTranslatef,glScalef,glRotatefメソッドをコールし,表示位置を決めます。

次に,renderableのrenderメソッドをコールして,描画を行います。イメージを表示する場合は,org.progx.jogl.rendering.ReflectedQuadクラスのrenderメソッドを使用します。少し長いので,核の部分だけ示します。

    gl.glBegin(GL.GL_QUADS);
 
    // render solid/upright texture
    gl.glColor4f(antiAliased ? 1 : alpha,
                 antiAliased ? 1 : alpha,
                 antiAliased ? 1 : alpha, alpha);
    gl.glTexCoord2f(tx2, ty1);
    gl.glVertex3f(x + width, y + height, z);
    gl.glTexCoord2f(tx1, ty1);
    gl.glVertex3f(x, y + height, z);
    gl.glTexCoord2f(tx1, ty2);
    gl.glVertex3f(x, y, z);
    gl.glTexCoord2f(tx2, ty2);
    gl.glVertex3f(x + width, y, z);
        
    alpha /= reflectionTransparency;
        
    gl.glColor4f(antiAliased ? 1 : alpha,
                 antiAliased ? 1 : alpha, 
                 antiAliased ? 1 : alpha, alpha);
    gl.glTexCoord2f(tx2, ty2);
    gl.glVertex3f(x + width, y, z);
    gl.glTexCoord2f(tx1, ty2);
    gl.glVertex3f(x, y, z);
    gl.glColor4f(0.0f, 0.0f, 0.0f, 0.0f);
    gl.glTexCoord2f(tx1, ty2 * (1 - fadeDistance));
    gl.glVertex3f(x, y - (height * fadeDistance), z);
    gl.glTexCoord2f(tx2, ty2 * (1 - fadeDistance));
    gl.glVertex3f(x + width, y - (height * fadeDistance), z);
 
    gl.glEnd();

最初のglBeginメソッドの引数GL_QUADSは,複数の四角形を描画することを意味しています。

その後は,テクスチャ座標を指定して,四角形の頂点を設定するだけ。そうです,今までこの解説で行ってきたのとたいして変わりません。

四角形が二つあるのは,床に反射したような効果を出すためです。図3をよーく見てください。普通に描画されたイメージの下に,薄くイメージが描画されているのがわかりますか。これが,二つ目の四角形です。

もちろん,ここで示したソースがすべてではありませんが,基本的には四角形にテクスチャとしてイメージを貼り,それを移動させるだけです。

あとは作る人のアイデアしだいです。

Aerithはイメージの表示だけでなく,フェーディングなど様々な効果を駆使しています。コードを追っていくと,いろいろな発見があるはずです。

:JavaOneのデモではGoogle Mapsを使用していましたが,java.netで公開されているバージョンではhttp://mapwow.com/の地図を使用しています。

XTrans

Aerithは,どちらかというと今までのGUIとは異なる見せ方,異なる操作法を指向しています。ここでもう一つ紹介するXTransは,Aerithとは異なり,既存のGUIの方向性は変えていません。

ただ,ちょっとだけ3Dで味付けをしているのです。事前知識がないままXTtransを触ったら,3Dが使用されていることに気付かないかもしれません。でも,ほんのちょっとだとしても,とても効果的な味付けになっています。

まずは試してみましょう。XTransはJOGLのデモに含まれています。もし,jogl-demos.jarをダウンロードしていないのであれば,jogl-demosプロジェクトにJava Web Start版があるので,それを試してみてください。なお,実行にはJava SE 6が必要です。

ダウンロードしたjogl-demos.jarは,コマンドラインから実行できます。実行するときには起動オプション-Dsun.java2d.opengl=trueを付加して起動してください。

C:\temp>java -Dsun.java2d.opengl=true -classpath 
jogl-demos.jar;jogl-demos-util.jar demos.xtrans.Main

スペースの都合で2行になっていますが,実際には1行で入力してください。

起動すると,ごくごく普通のウィンドウが表示されます。メニューバーの[Actions]を選択し,[Add Table]か[Add Tree]をクリックしてみてください。

えっ!

という感じではないですか。そうなんです。[Add Table]や[Add Tree]をクリックするとJInternalFrameが表示されるのですが,その表示の方法が普通ではないのです。

パタンと倒れるように表示されたり,横からヌーッと表れたり,フェーディングして表れるのです。これらの効果はJInternalFrameを閉じるときにも使われます。

(再生ボタンを押してください)

どうですか,衝撃的ではないですか?

筆者は,はじめてこれを見たとき,目が点になりました。こうくるとは,という感じです。

これはどうやって実現しているのでしょうか。キーとなるのがJava SE 6のJava2Dの実装です。

先週,解説したように,Java SE 6ではJava2Dが使用しているOpen GLのパイプラインに対してJOGLから直接アクセスできるようになりました。

そこで,Java 2Dが描画するものを,JOGLが横から取り上げてしまい,効果を付け足して描画する,という処理を行っています。このとき,Java 2Dの描画対象はテクスチャに変換されます。あとはAerithと同様に,ポリゴンにテクスチャを貼り,パタンと倒れるものは回転,横から出てくるものは移動のアニメーションをしながら描画します。

Java2DとJOGLの架け橋となっているのが,com.sun.opengl.impl.Java2Dクラスです。長くなるのでコードは示しませんが,比較的簡単にこのような効果を実現できます。

ここで示した3Dによる効果は,アプリケーションの機能にはまるで関係ありません。それでも,見せ方がクールになるだけで,アプリケーションの魅力がグンと上がるはずです。

3カ月間のまとめ

JavaからOpenGLを使ってみようということで,3カ月にわたってJOGLを解説してきました。

これをきっかけに3D CGの世界に興味を持っていただければ幸いです。

バリバリの3Dのアプリケーションを作るのもいいですが,筆者が特に強調したいのは,2Dのアプリケーションに3Dを取り入れることです。3Dの要素を取り入れることで,ユーザビリティを向上したり,見た目をクールにできます。

このような用途でOpenGLを使用する場合は,それほど知識は必要ありません。それよりも,どうやって見せるか,どうやって操作させるかというアイデアの方が重要になります。

ここでキーとなるのが,テクスチャです。

2Dのアプリケーションを3Dで扱う場合,ほとんどテクスチャとして扱えます。Aerithのイメージもそうですし,XTtransのJInternalFrameも最終的にはテクスチャに還元されます。

XTransの場合はテクスチャを貼ったポリゴンの回転・移動などを行っていましたが,例えばドロップシャドウをつけることなども可能です。今回は解説しませんでしたが,シェーディング言語を使うことでエンボス加工などもできます。

Swingは何となく垢抜けない,と思っているなら,それは間違いです。やろうと思えばAerithのようにかっこいいGUIも記述できるのです。さらに,そこにJOGLが加われば,もっとクールになるに違いありません。

どうですか,皆さんもやってみませんか。

さて,12月には待ちに待っていたJava SE 6がリリースされます。そこで,来月からはJava SE 6の新しい機能について解説していきましょう。お楽しみに。

著者紹介 櫻庭祐一

横河電機の研究部門に勤務。同氏のJavaプログラマ向け情報ページ「Java in the Box」はあまりに有名