■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
                      2008年10月05日

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

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


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


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


さて、Java 3Dを使うと単に3Dグラフィックスのアプリケーションが
楽に作れるというだけでなく、ステレオ画像(立体画像)(あるいは
アニメーションにすれば立体映像)も簡単に作成することができます。


最近は、アミューズメント・パークなどでステレオ映像(立体映画)
が上映されることも多くなりましたので、まず、その仕組みからお話
しておきましょう。


そもそも人間(および他の動物たち)は目を2つ持つことによって、
周囲のものを立体的に見ることができます。

周囲のものの見え方は、視点の位置によって違いますが、左目と右目
では位置が違うため、同じものを見ているようでも少し違った画像が
網膜に映っています。そして、この違いを脳で瞬時に処理して立体感
を得るようになっています。

この左目で見える画像と右目で見える画像を別々の写真に撮っておき
左目には左目用の写真だけを、右目には右目用の写真だけを同時に
見せるようにすれば、写真が立体的に見えることになります。

(1) このことから、ステレオ・スコープという装置が作られました。
ステレオ・スコープは、双眼鏡のように2つの覗き穴がついた装置で
両目で覗き込むと左目には左目用の写真だけが、右目には右目用の写真
だけが見えるようになっています。これらを同時に見ることによって、
写真が立体的に見えるわけです。

皆さんも、子供の頃に、玩具の一種としてステレオ・スコープを覗いた
ことがあるのではないでしょうか。

一方、一枚の写真を細かい多数の細部の区画に分け、各区画ごとに左目用
の細部の画像と右目用の細部の画像を描いて、その上に区画ごとに小さな
かまぼこ型のレンズを貼り付け、左目から見ると、各レンズには左目用の
画像だけが映り、右目から見ると右目用の画像だけが映るようにしたもの
も作られました。
これだと一枚の写真を見ただけで立体的に見えるわけですが、その代わり
写真がギザギザ状に見えてあまりきれいではありません。


ステレオ・スコープの立体画像の仕組みは、映画にも応用されるように
なりましたが、映画の場合は複数の人が同時に見ますから、ステレオ・
スコープを使う訳にはいきません。

(2) そこで最初にとられた方法は、例えば左目用の画像(映像)は赤色の単色画像
にしておき、右目用の画像(映像)は緑色の単色画像にしておき、スクリーン上
に同時に赤色の画像と緑色の画像を映します。
それを観客には左目は赤色の光だけを通し、右目は緑色の光だけを通す、特殊な
メガネをかけてもらって見てもらいます。
こうすれば、複数の観客が同時に立体画像(立体映像)を見られるわけですが、
ただし、映像をカラーにすることができないので、おもしろくありません。


(3) そこで登場したのが、偏光フィルターを使う方法です。
光は電磁波と呼ばれる波であり(素粒子物理学あるいは量子力学のレベルで
言えば、光は粒子の性質も持っていますが、細かい話なので無視します)、
(電場と磁場の)振動によるものです。この波は横波であり、波の進行方向に
対して直角の方向に振動します。
この振動も360度、あらゆる角度に振動する可能性があるわけですが、偏光フィ
ルターというフィルターはこのうちの特定の角度に振動する光だけを通します。

そこで、特定の色だけを通す眼鏡の代わりに、例えば左目には縦方向の振動の光
だけを通す偏光フィルターを、右目には横方向の振動の光だけを通す偏光フィルター
を取り付けた眼鏡を着用し、左目用の画像は縦方向の振動の光のみで映写し、右目用
の画像は横方向の振動の光のみで映写すれば、カラーの立体画像(立体映像)を
見ることができます。

現在、主流になっている立体映画はこの偏光フィルターを使ったものです。


しかし、この偏光フィルターを使った方法は特殊な装置を必要とするため、
皆さんのPCでは利用できません。

また、(2)の方法は、(左目は赤色、右目は緑色といった)特殊な色眼鏡を必要と
するため、これも却下となります。


というわけで、これから紹介する立体画像(立体映像)のプログラミングは必然的
に(1)のステレオスコープの原理を利用したものになります。
((2)や(3)による方法も(1)の方法がわかればプログラミング自体は簡単に行え
ます。)



では、立体画像(立体映像)のプログラミングの仕方を説明しましょう。


この立体画像を描くための機能は、Canvas3Dクラスに用意されています。
そして、立体画像を描くためには、Canvas3Dクラスを以下のように使用します。

まず最初に左目用の画像と右目用の画像を描くために、Canvas3Dインスタンス
を2つ用意します。

GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
Canvas3D leftEyeCanvas = new Canvas3D(config);
Canvas3D rightEyeCanvas = new Canvas3D(config);

このうちの一つのCanvas3Dインスタンスは左目用の画像を、もう一つのCanvas3Dインス
タンスは右目用の画像を描くために使うのですが、このことは、以下のようなソース
コードで指定します。

leftEyeCanvas.setMonoscopicViewPolicy(View.LEFT_EYE_VIEW);
rightEyeCanvas.setMonoscopicViewPolicy(View.RIGHT_EYE_VIEW);

これらのうち、leftEyeCanvasのほうを使ってSimpleUniverseのインスタンスを生成
しておくことにしましょう。(rightEyeCanvasのほうを使っても構わないのだが、
とりあえず、leftEyeCanvasのほうにしておく。)

SimpleUniverse universe = new SimpleUniverse(leftEyeCanvas);


さて、左目で見たときの眺望(View)と右目で見たときの眺望の違いは、左目と右目の
間の距離に依存しますので、それも設定しておきます。
(実際には、基準の視点に対する左目の位置のずれと右目の位置のずれを設定します。)

そのためには、まず、眺望のオブジェクト(Viewオブジェクト)を取り出しておきま
しょう。
これにはvol.118で紹介したgetViewer()メソッドとgetView()を使って以下のように
します。

View view1 = universe.getViewer().getView();

ここで取り出したViewオブジェクト(ここではview1という変数名にしている)は、
立体画像でない場合は左目用/右目用の区別はありませんが、立体画像にする場合
は区別をしなければなりません。ここでは、view1を左目用とすることにします。

そうすると、右目用のViewオブジェクトを別途作成しなければなりません。
左目の位置が決まれば、右目と左目の間の距離あるいは、右目の位置が左目の位置から
どれだけずれているかを指定してやれば、右目の眺望も決まります。

これは、次のようにします。

まず、観察者の身体を表現するオブジェクト(PhysicalBodyというクラス名になっている)
がViewによって提供されていますので、それを取り出します。これはViewオブジェクトの
getPhysicalBody()というメソッドを使って、次のようなソースコードで行えます。

PhysicalBody observBody = view1.getPhysicalBody();

続いて、観察者の左目の位置と基準の視点の位置のずれを設定します。これはPhysicalBody
オブジェクトのsetLeftEyePosition()というメソッドを使って、次のようなソースコード
で行えます。(PhysicalBodyオブジェクトと言っても、物理的な身体の情報をすべて保持
しているわけではありません。実際に必要な情報は眺望やサウンド(音付きのアプリケー
ションを作るためにサウンドも扱える)に関するものだけなので、目や耳の位置の情報
くらいしか保持していません。)

observBody.setLeftEyePosition(new Point3d(-0.006,0.0, 0.0));

上のソースコードでは、左目の位置を基準の視点よりX軸のマイナス方向に(つまり左に)
0.006だけずれているものと設定しています。

同様にして、右目は基準の視点よりX軸のプラス方向に(つまり右に)0.006だけ
ずれているものと設定しましょう。

observBody.setRightEyePosition(new Point3d(+0.006,0.0, 0.0));


ここで、右目用のViewオブジェクトもインスタンス生成しておきます。

View view2 = new View();

この右目用のViewオブジェクトに左目用のViewオブジェクトのものと同じ観察者の
身体(PhysicalBodyオブジェクト)、同じ物理的環境(PhysicalEnvironmentオブジェ
クト)、同じ基準視点(ViewPlatform)を設定してやります。
これらは、以下のようなソースコードで行えます。

view2.setPhysicalBody(observBody);
view2.setPhysicalEnvironment(view1.getPhysicalEnvironment());
view2.attachViewPlatform(universe.getViewingPlatform().getViewPlatform());

ただし、今の時点では、まだview2が左目の眺望なのかあるいは右目の眺望なのか、
明確になっていません。まだ、rightEyeCanvasに結び付けていないからです。

というわけで、下記のようにしてrightEyeCanvasに結び付けておきます。

view2.addCanvas3D(rightEyeCanvas);


あとは、これらのCanvas3DオブジェクトをJFrameのお腹に貼り付けておけば作業
完了です。

ただし、leftEyeCanvasが左側、rightEyeCanvasが右側にくるように貼り付ける位置
を調整する必要がありますし、これらの(およびJFrameウインドウの)サイズを調整
しておく必要があります。


では、これらを踏まえて、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. 不許無断複製