Go to Contents Go to Java Page
Project Looking Glass
 
 

はじめての LG3D プログラミング

- LG3D で Hello, World! その 1 -

 
 

とりあえず、一番はじめのプログラムということだと、やっぱり Hello, World! でしょう。

Hello, World! を作るとしても、いろいろと方法があります。単に System.out.println("Hello, World!"); で実現できれば簡単でいいのですが、そうもいきません。

そこで、今回は Hello, World! と書いたイメージファイルを読みこんで、表示するという手法を使ってみようと思います。

使用した LG3D のバージョンは Release-0.7.0 です。

  1. 材料はなに ?
  2. とりあえず作ってみる
  3. カーソルを変更してみる
  4. サムネイルをどうにかする
  5. おわりに
 
 

材料はなに ?

 
 

LG3D でアプリケーションを作成するには、org.jdesktop.lg3d.wg パッケージのクラスを使用します。wg は Widget の略です。SWT の W も Widget の略ですが、GUI の部品と考えることができます。ちなみに AWT の W は Widge ではなく Window です。

基本になるクラスは次の 2 つです。

  • Component3D クラス
  • Container3D クラス

Component3D はすべての Widget のベースとなるクラスで、AWT の Component や Swing の JComponent に相当します。しかし、 Component3D クラス自体は表示されることはありません。表示されるのは Component3D オブジェクトに addChilde されるシェイプです。

Component3D オブジェクトに追加することのできるクラスは org.jdesktop.lg3d.sg.Node クラスの派生クラスです。たとえば、org.jdesktop.lg3d.utils.shape.Box クラスなどの基本的な形状を表すクラス (プリミティブと呼びます) や、org.jdesktop.lg3d.utils.shape.ImagePane クラスなどの板状のパネルを表すクラスなどがあります。

Container3D クラスは Component3D クラスの派生クラスで、AWT の Container クラスや Swing の JContainer クラスに相当します。

Component3D クラスの派生クラスですが、addChild できるのは Component3D オブジェクトだけという違いがあります。つまり、Container3D クラスは Component3D クラス専用のコンテナになるわけです。

Component3D も Container3D も複数のチャイルドを持つことができます。addChild していくと最終的にはツリー構造ができあがります。Java3D ではこのツリーをシーングラフと呼びます。LG3D ではシーングラフを意識することはほとんどありませんが、シーングラフという言葉は頭の片隅にでもおいておいてください。

さて、次に登場するのが Container3D クラスの派生クラスである Frame3D クラスです。一見すると Frame クラスや JFrame クラスに対応するような感じがしますが、機能的にはずいぶん違います。それでも Frame クラスや JFrame クラスが 2D アプリケーションのベースとなるように、Frame3D も 3D アプリケーションのベースとなるものです。

後は、Component3D に追加するものを準備しなくてはいけません。今回はイメージで Hello, World! を表示するので、それに使えそうなクラスはないかなぁと探してみたら、ありました。

org.jdesktop.lg3d.utils.shape.ImagePanel クラスです。このクラスは 1 枚のパネルにイメージを張ってくれるというクラスです。これを使って Hello, World! を作ってみます。

 

 
 

とりあえず、作ってみる

 
 

材料もそろったので、作っていきましょう。

サンプルのソース HelloWorld1.java

先ほどいったようにベースになる Frame3D オブジェクトに Component3D オブジェクトをはって、そこに ImagePanel オブジェクトを追加するという構造になります。ちなみに ImagePanel オブジェクトに貼るイメージはこれです。

Hello World

 

            Frame3D frame3d = new Frame3D();
		  
            ImagePanel panel = new ImagePanel(IMAGE_FILE, WIDTH, HEIGHT);
 
            // ImagePanel は直接 Frame3D (Container3D)
            // に追加することはできないが、
            // Component3D に追加することができる
            Component3D comp3d = new Component3D();
            comp3d.addChild(panel);
 
            // Frame3D に追加できるのは Component3D だけ
            frame3d.addChild(comp3d);
 
            // サイズ変更 奥行きも設定する
            frame3d.setPreferredSize(new Vector3f(WIDTH, HEIGHT, DEPTH));
        
            // お約束
            frame3d.changeEnabled(true);
            frame3d.changeVisible(true);

まずはじめに Frame3D オブジェクトを生成します。Frame クラスなどと違って、引数はありません。

次に ImagePanel オブジェクトを生成します。コンストラクタの第 1 引数は画像ファイル名、第 2, 3 引数がパネルの大きさになります。

ImagePanel オブジェクトができたら、それを追加する Component3D オブジェクトをつくり、そこに addChild メソッドを使用して ImagePanel オブジェクトを追加します。

そして、それを Fraem3D オブジェクトに追加します。

Frame3D 自体は描画されることはないのですが、大体の目安となる大きさをセットしておきます。サイズの設定には Swing で使われる JComponent#setPreferredSize メソッドと同様です。

Frame3D オブジェクトに対しても Component3D#setPreferredSize メソッドを使用してサイズを設定するのは、LG3D がフレームを描画するときにレイアウトマネージャを使用しているからです。

Swing ではフレームの配置はプラットフォームによって行われますが、LG3D では LG3D の内部でおこなわれます。このため、レイアウトマネージャを変更すれば、配置方法も変わってきます。

最後にアプリケーションを表示させるために、お約束が 2 つ。

changeEnabled メソッド、changeVisible メソッドです。

changeEnabled メソッドは、シーングラフが完成したので、表示できる状態にするためのメソッドです。3D グラフィックの言葉ではピッキングといいますが、マウスでクリックしたりすることができるようになります。

また、シーンマネージャ (3D 版のウィンドウマネージャみたいなものです) に対して、アプリケーションをアクティブにするということもおこなっています。

ただし、このメソッドをコールしても表示はされません。表示するのは最後の changeVisible メソッドをコールするときです。これは AWT や Swing でも同じですね。

ところで、上にあげたソースの中ではサイズは定数で WIDTH, HEIGHT, DEPTH としてありますが、実際の値はどうなっているのでしょう。

LG3D での単位系は Java3D のそれと同じで、1m が 1 となります。ですから 0.5 だったら 50cm です。

HelloWorld1.java で使用したイメージは 200 × 25 pixel ですが、72 dpi で作りました。dpi は dot/inch のことで、1 inch は2.54 cm ですから、LG3D での大きさは以下のようになります。

    // 画像の大きさ 200x25 pixel
// メートル変換用 0.0254 [inch/m] / 72.0f [pixel/inch]
private static final float WIDTH = 200.0f * 0.0254f / 72.0f;
private static final float HEIGHT = 25.0f * 0.0254f / 72.0f;
private static final float DEPTH = 0.005f;

厚みは 5mm です。ペラペラですね。

ついでに座標軸ですが、もちろん z 軸があります。下の図に表したように x 軸は左から右の方向、y 軸は AWT や Swing と違って下から上が正の方向になります。

z 軸は画面を飛び出す方向が正です。

座標軸

それでは、コンパイル、実行してみましょう。サンプルは lg3d ディレクトリに hw ディレクトリを作成し、そこにおくことにしました。サンプルのパッケージは samples です。クラスパスには lg3d-core.jar を含めてください。

> cd hw
> javac -cp ../lib/ext/lg3d-core.jar samples/HelloWorld1.java

実行は LG3D Tutorials で公開されている runtutorial シェルスクリプトを使えたのですが、残念ながら今は公開してません。

しかたないので、同じようなシェルスクリプト runsample を作りました。

このシェルスクリプトの 2 行目に LG3DHOME 環境変数が設定されていますが、ここを LG3D をインストールしたディレクトリに変更してから使ってください。

同じように Windows ようの runsample.bat も作りましたので、Windows な方はこちらを使ってください。やはり、2 行目の LG3DHOME を変更してください。

Linux 用の起動用バッチファイル runsample
Windows 用の起動用バッチファイル rusample.bat

さて、実行してみましょう。

> ./runsample samples.HelloWorld1

ログがずらずらと表示されますが、その後に LG3D が表示されて HelloWorld! も表示されるはずです。

Hello World

ちなみにこれは WindowsXP で実行した結果です。

さて、表示はされましたが、表示されただけです。

次は、いろいろと機能をつけ加えていきましょう。

 

 
 

カーソルを変更してみる

 
 

前のプログラムはドラッグすればフレームの移動を移送させることができるのですが、そのためにマウスカーソルが移動用に変更されてしまっています。

それもちょっとかっこ悪いので普通のカーソルに戻してみましょう。

カーソルを変更するのは簡単です。Component3D#setCursor メソッドを使うだけです。

サンプルのソース HelloWorld2.java

setCursor メソッドの引数は org.jdesktop.lg3d.wg.Cursor3D オブジェクトです。これも AWT の Cursor クラスに対応するものです。

このクラスにはよく使われるカーソルが定数として定義されています。デフォルトのカーソルは Cursor3D.DEFAULT_CURSOR を使います。

            // カーソルの変更
            comp3d.setCursor(Cursor3D.DEFAULT_CURSOR);

さて、これでマウスのカーソルも変えることもできました。実行するとマウスが Hello, World! の領域に入ってもカーソルの形状は変化しなくなっているはずです。

Cursor3D という名前のとおりこのカーソルも 3D として実現されています。フレームの領域に入るとカーソルが拡大さるのがが分かります。

ソースを見ると分かるのですが、本当に四角錐を 3 角形のポリゴンと 4 角形のポリゴンで構成しています。こんなところまで、凝った演出をしているなんて憎いですね。

Cursor

 

 
 

サムネイルをどうにかする

 
 

さて、次はサムネイルです。

LG3D でいうサムネイルはタスクバーに表示されているアプリケーションのアイコンのことです。起動用のアイコンと区別するためにこのようないいかたがされているようです。

デフォルトのサムネイルは青い半透明のパネルです。これでもいいといえばいいのですが、手を抜いたということがばれてしまうので、やっぱりここも変更してみましょう。

サムネイルを扱うためのクラスは org.jdesktop.lg3d.wg.Thumbnail クラスです。Thumbnail クラスは Component3D クラスの派生クラスですが、扱いとしては Frame3D クラスに似ています。

つまり、Thumbnail オブジェクトに Component3D オブジェクトを追加していきます。

サンプルのソース HelloWorld3.java

ここではサムネイルをフレームで表示されているものと同じにしてみましょう。

サムネイル表示は縮小表示されるので、そのままだと分かりにくいこともあります。そこで、適当に ImagePanel オブジェクトの大きさを大きくしてみました。

また、サムネイルもフレームと同様に setPreferredSize メソッドを使用してサイズを設定しておきます。

Thumbnail オブジェクトの準備が整ったら Frame3D オブジェクトに Frame3D#setThumbnail メソッドを使用して設定します。

            // サムネイルの生成
            Thumbnail thumbnail = new Thumbnail();
 
            // サムネイル用のシェイプ 縮小表示されるので大きめにする
            ImagePanel thumbnailPanel = new ImagePanel(IMAGE_FILE, WIDTH*4f, HEIGHT*4f);
            Component3D thumbnailComp3d = new Component3D();
            thumbnailComp3d.addChild(thumbnailPanel);
 
            // サムネイルに Component3D を追加する
            thumbnail.addChild(thumbnailComp3d);
 
            // サムネイルもサイズを設定する
            // 縮小表示されるのでサイズは同じでかまわない
            thumbnail.setPreferredSize(new Vector3f(WIDTH*4f, HEIGHT*4f, DEPTH));
 
            // Frame3D にサムネイルを設定
            frame3d.setThumbnail(thumbnail);

コンパイルして、実行してみましょう。

ちゃんとサムネイルが表示されましたね。フレームにフォーカスがあたっているときはまっすぐ、外れると斜めに向きを変えるのがお分かりですか。

サムネイル

 

 
 

おわりに

 
 

これだけだとちょっとものたりないですが、とりあえず Hello, World! を表示して、サムネイルの表示までおこなってみました。

でも、やっぱりもうちょっと普通のアプリケーションみたいにしたいですよね。

今は単に表示しているだけで、インタラクションが何もありません。インタラクションをおこなうにはイベント処理を加えなくてはいけません。

というわけで、次回はそのあたりのことに挑戦です。

 

今回使用したサンプルはここからダウンロードできます。

 

(Sep. 2004)
(改訂 Feb. 2005 Release-0.61 に対応)
(改訂 June. 2005 Release-0.62 に対応)
(改訂 Aug. 2005 Release-0.7.0 に対応)

 
 
Go to Contents Go to Java Page