■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
                      2008年07月06日

    楽しいJava講座 - 初心者から達人へのパスポート
                  vol.110

                                セルゲイ・ランダウ
 バックナンバー: http://www.flsi.co.jp/Java_text/
■■■■■■■■■■■■■■■■■■■■■■■■■■■■■


[このメールマガジンは、画面を最大化して見てください。]


========================================================
◆ 01.3Dグラフィックスのアプリケーション開発
========================================================


さて、以前2次元のグラフィックスのアプリケーションを作成した
ときは、画面の右方向にx軸、下方向にy軸が取られ、y軸の向きは
数学における標準的な向き(上向き)とは逆に、下にいくほどy座標
の値が大きくなることをお話しました。

これは、OS(基本ソフト)に合わせてy座標が設定されたためなのですが、
Java 3Dではどうでしょうか。

実は、Java 3Dでは、座標軸の向きは数学の標準に合わせられています。

具体的には、画面の右方向にx軸、上方向にy軸(上にいくほどy座標の
値が大きくなる)となっています。
そして、画面に垂直に画面からあなたの方向に向かって、z軸が出て
います。

数学の標準では、3次元の座標軸は斜め方向から見た状態に描くのが
普通ですから、見る方向は数学の標準と違っているかも知れませんが、
3つの座標軸の相対的な向きは数学と同じですね。

そして、Java 3Dでは、この3次元空間を宇宙(Universe)と呼んでいます。
宇宙と言っても、コンピューター上で表現する宇宙は仮想的なものに
過ぎないですから仮想的宇宙(VirtualUniverse)と呼ぶクラスで3次元空間
が表現されているのですが、ただしこのVirtualUniverseは取り扱いが
面倒なので、通常はその簡易版として用意されたSimpleUniverseという
クラスが使われます。


そこで、前回Java 3Dのインストールの確認用に実行したプログラム
を再度、見てください。

SimpleUniverse universe = new SimpleUniverse();

という行がありますね。ここで宇宙のインスタンスを作成している
わけです。

そして、この宇宙の中にさまざまな物体を作り込んで、それらを描画
するわけですが、(たとえば自転車などの)複雑な形をした物体は、
基本的な図形を複数組み合わせることによって作っていきます。

その場合、その複雑な形をした物体を構成する複数の基本図形を一つの
グループにしておいて、グループごとにひとまとめに移動するといった
操作ができないと不便ですね。
複雑な形をした物体全体を移動したいのに、その構成要素の一部の図形
だけが移動するのでは不便です。


というわけで、Java 3Dでは、グループの概念が用意されており、主に
BranchGroupというクラスによって表現されています。(他にもグループ
を表現するクラスがあります。)

Branchとは枝の意味ですが、ちょうど一本の木から複数の枝が枝分かれ
し、その各枝がさらに複数の枝に枝分かれするというように、細かく
枝分かれしていく様子を表現することからBranchという名前がついて
います。
たとえば、自転車という物体の場合は、自転車全体を表すグループをさら
に細かく、前輪を表すグループ、後輪を表すグループ、ハンドルを表すグ
ループ、フレームを表すグループ、サドルを表すグループ、ペダルを表す
グループといった、その構成要素となっている小さいグループ(サブ
グループ)に分けることができ、さらにそのサブグループ、たとえば前輪
のグループは、タイヤのグループとスポークのグループと・・・といった
より細かいグループに分けることができます。
これらは、自転車が前輪、後輪、ハンドル、フレーム、・・・に枝分かれし、
前輪がさらにタイヤ、スポーク、・・・に枝分かれし、・・・というように
枝分かれによって表現することができます。そして最終的な末端の部分を
葉(Leaf)と呼び、そこには基本図形などオブジェクトがつなぎとめられ
ることになります。
(なお、枝分かれは、あとで出てくるaddChild()というメソッドによって
実現されます。)

そして、複数の物体をグループの各枝につなぎとめておき、その木
(グループ)の根っこを宇宙につなぎとめておけば、いつでも宇宙から
各物体にたどっていくことができ、また、複数の物体をまとめて(移動
などの)操作することができるわけです。

(BranchGroupは、あくまで物体の操作や管理を楽にするための道具
に過ぎず、BranchGroupの枝は描画されません。)


というわけで、前回のプログラムでは、

BranchGroup group = new BranchGroup();

という行によってグループのインスタンスを作成し、

group.addChild(new ColorCube(0.3));

という行によって、グループの枝に物体(ここでは色付きの立方体)を
つなぎとめています。(addChildを直訳すると、子供を追加するという
意味になりますが、ここでは枝分かれした枝の先に物体を追加すると
いうことを意味します。
そして、枝の根元を親(parent)、先を子(child)というふうに表現
します。)
ここで、Cubeというのは立方体の意味で、ColorCubeというのは色付きの
立方体を表現するクラスです。


そして、前回のプログラムでは、

universe.addBranchGraph(group);

という行によってグループの根っこを宇宙につなぎとめています。
(addBranchGraphは直訳すると枝の図を追加するというような意味に
なりますが、ここでいうgraph(図)とは、複数の枝とそのつなぎ目の
点で構成される構成図の概念を意味します。実際に枝の図が描画される
わけではありません。)

┌補足─────────────────────────┐
ここで言うGraphは、数学のグラフ理論のグラフを意味しており、
通常我々が使うグラフとは意味が異なります。
グラフ理論のGraphはエッジ(edge)と呼ばれる枝とノード(node)
と呼ばれる枝のつなぎ目の点あるいは頂点がそれぞれ複数組み合わ
さって構成される構成図の概念を意味します。
そして上記のgroup.addChild()はノード(ここではColorCubeと
いう物体がノードになっている)を追加するメソッドであり、
追加された物体は描画されますが、グラフ自体は
あくまで概念のみであり描画されません。
└───────────────────────────┘



ところで、前回のプログラムを実行したときには、立方体ではなく
正方形しか見えませんでしたね。

これは、実は、立方体を真正面から見たために正面の正方形の部分
しか見えなかったためです。

ここら辺の事情を調べるためには、残りの

universe.getViewingPlatform().setNominalViewingTransform();

という行を理解しておく必要があります。


まず、getViewingPlatform()というメソッドは、ViewingPlatformを
取り出すためのメソッドです(なんて、言うまでも無いですね)。
このViewingPlatformというのは、宇宙を観察する「視点」を意味し、
宇宙の原点からどの方向にどれだけ離れた位置から観察するか、が
関心事になります。

そして、ViewingPlatformのsetNominalViewingTransform()という
メソッドは、視点をデフォルト値だけ移動するメソッドで、その
デフォルト値は、特に設定を変更していない場合はz軸の正の方向に
1/(tan(PI/8))だけ移動した位置で、ここから宇宙の原点が画面の
真ん中に見える方向に宇宙を観察することになります。

そのとき、原点を通ってz軸に垂直な面(xy平面)において、画面の
左右の端のx座標が、それぞれ-1と1(つまり、このxy平面の画面の
左端のx座標が-1で、画面の右端のx座標が1)になるように見え方が
自動調整されます。)
(なお、上記で画面の左端のx座標が-1、画面の右端のx座標が1となって
いることからもわかると思いますが、2次元のグラフィックスとは異なり、
Java 3Dにおける座標値の単位はピクセルではなく、独自の単位になって
います。)


したがって、前回のプログラムでは立方体を真正面から見ていたわけで、
正方形の部分しか見えなかったわけです。

これを立方体らしく見たい場合は、斜め方向から見るようにすればいい
でしょう。
これをプログラミングしてみましょう。



その前に、現在はGUIのアプリケーションのお話をしているのですから、
この(正方形に見える)立方体をSwingのJFrameの上に描画するように
プログラムを変更しておくことにしましょう。

JFrame上で3Dグラフィックスを描画するためには、2次元のときとは異な
り、JPanelなどの通常のGUI部品を直接描画の画板(キャンバス)にする
ことはできず、3D用に作られた画板としてCanvas3Dというクラスを使用
する必要があります。

このクラスのインスタンスは次のようにして生成することができます。

GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
Canvas3D canvas = new Canvas3D(config);

まず、上のgetPreferredConfiguration()というメソッドはSimpleUniverse
のスタティック・メソッドで、現在使用しているシステム(コンピューター)
の描画装置(ディスプレイなど)の特性を表現するGraphicsConfiguration
というオブジェクトを返してくれます。

そして、
Canvas3D canvas = new Canvas3D(config);
を実行すると、そのGraphicsConfigurationオブジェクトの特性を使った
Canvas3Dオブジェクトが生成されます。

この場合、SimpleUniverseはこのCanvas3Dの上に描くことになるので、次の
ようにインスタンス生成する必要があります。

SimpleUniverse universe = new SimpleUniverse(canvas);



では、実際にこれらのコードを使って、(正方形に見える)立方体をSwingの
JFrameの上に描画するプログラムを作ってみましょう。


Eclipseを起動して、VisualEditorで下記のようなクラスを作成しましょう。
(VisualEditorをまだインストールしていない人は、vol.108に従って
インストールしておいてください。)

(1) パッケージ・エクスプローラーの中のJStudy3(プロジェクト)の中の
(srcの中の)jp.co.flsi.lecture.java3d(パッケージ)を右クリックし、
「新規」→「その他」を選択します。

(2) Javaの中のVisual Classを選択し、「次へ」ボタンをクリックします。

(3) 「名前」欄には
ColorCubeJFrame
と入力し、「Style:」欄ではSwingの中のFrameを選択し、
「public static void main(String[] args)」と
「Inherited abstract methods」にチェック・マークを入れて
「終了」ボタンをクリックします。

(4) ColorCubeJFrame.javaのinitialize()メソッドのソース・コードを
次のように編集しましょう。

--------------------------------------------------------
   private void initialize() {
      this.setSize(300, 200);
      this.setContentPane(getJContentPane());
      this.setTitle("ColorCubeの描画");
     
      GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
      Canvas3D canvas = new Canvas3D(config);
      SimpleUniverse universe = new SimpleUniverse(canvas);
      BranchGroup group = new BranchGroup();
      group.addChild(new ColorCube(0.3));
      universe.getViewingPlatform().setNominalViewingTransform();
      universe.addBranchGraph(group);
      getJContentPane().add(canvas);
   }
--------------------------------------------------------
(新出のクラス名に赤いアンダーラインが付くことと思いますが、例によって
コンテンツ・アシスト(Ctrl + スペース・キー)の機能を利用して、import文
を自動的に挿入するようにして下さい。)


(5) ファイルを保管(Ctrl+S)した後、ColorCubeJFrameを実行してみましょう。

ウインドウが開いて、赤色の正方形が表示されましたか。



では、今日はここまでにします。

何か、わからないところがありましたら、下記のWebページまで質問を
お寄せください。



┏━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
★ホームページ:
      http://www.flsi.co.jp/Java_text/
★このメールマガジンは
     「まぐまぐ(http://www.mag2.com)」
 を利用して発行しています。
★バックナンバーは
      http://www.flsi.co.jp/Java_text/
 にあります。
★このメールマガジンの登録/解除は下記Webページでできます。
      http://www.mag2.com/m/0000193915.html
★このメールマガジンへの質問は下記Webページにて受け付けて
 います。わからない所がありましたら、どしどしと質問をお寄
 せください。
      http://www.flsi.co.jp/Java_text/
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━┛

Copyright (C) 2008 Future Lifestyle Inc. 不許無断複製