■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
                      2008年08月17日

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

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


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


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

さて、前回は、球体に黄色い光を照射してみました。
そうすると、球体も黄色く光ります。

実は、この球体(Sphere)の表面はデフォルトでは白色になっています。
白色の物質に特定の色の光を照射すると、その物質が反射する光もその
色のままですから、その物質はその光と同じ色に見えます。
(蛍光物質(蛍光塗料などの原料になる物質)のように、照射された光
のエネルギーを吸収し、そのエネルギーを別の色の光に変換して放射
(発光)する物質もありますが、これは自ら発光する部類に属するので
ここでは除外します。)


┌補足─────────────────────────┐
自ら発光する物質を除くと、通常の物質は、外部から光が照射
されたときにその光を反射(通常は乱反射)することによって、
目に見えるようになります。

光の色というものは、光の周波数によって違いますが、白色光は
さまざまな周波数の可視光がほぼ均等に混ざったものです。
そして、このさまざまな周波数の可視光をほぼすべて反射する物質
が白色の物質ということになります。

特定の色をした物質というのは、その特定の色の光は反射する
けれど、それ以外の色の光はほとんど吸収してしまって反射し
ないという物質です。

なお、太陽光をプリズムを通して分解すると、周波数ごとに光が
分離されて、いわゆる虹のように色が見えてきますが、このとき
に見える色と、三原色を混ぜ合わせて作る人工的な色は異なりま
す。

たとえば、三原色のうちのredとgreenを混ぜ合わせて作った黄色
と太陽光をプリズムで分解してできた黄色は、同じように見えて
も実は異なるものです。

これがなぜ人間の目には同じように見えるかというと、人間の目
の視覚細胞には色に反応するものとしては3種類のものがあり、
それぞれred近辺の周波数に強く反応するもの、green近辺の周波
数に強く反応するもの、blue近辺の周波数に強く反応するもの
というように、3種類の細胞の反応の強度のバランスで、さまざ
まな色を識別するようになっているからです。

たとえば、虹の中の黄色の周波数に対して3種類の細胞が反応
するバランスと同様なバランスをred、green、blueの三原色の
光の混合比でうまく調整して再現してしまえば、人間の目には
同じ色に見えてしまうのです。

したがって、コンピューターのディスプレイやテレビの画面の
ように三原色を混ぜ合わせて色を表現する画面は、本当の自然な
色とは異なるものを表示しているわけですが、我々人間の目には
それが区別できないのです。

ちなみに、犬や猫や他の生物の目なら、違った見え方をします。
└───────────────────────────┘


では、物質が白色ではなく、特定の色だったらどうなるでしょうか。

試してみましょう。

たとえば、球体(Sphere)の表面を赤色にして黄色の光を照射したら
どうなるでしょうか。


下記のようにinitialize()メソッドを書き換えてみてください。

--------------------------------------------------------
   private void initialize() {
      this.setSize(300, 200);
      this.setContentPane(getJContentPane());
      this.setTitle("立方体と球体");

      GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
      Canvas3D canvas = new Canvas3D(config);
      SimpleUniverse universe = new SimpleUniverse(canvas);
      BranchGroup group = new BranchGroup();
      TransformGroup transGroup = new TransformGroup();
      transGroup.addChild(new ColorCube(0.3));
      Transform3D trans = new Transform3D();
      trans.setTranslation(new Vector3d(-2.0, -1.0, -5.0));
      transGroup.setTransform(trans);
      group.addChild(transGroup);

      BranchGroup group2 = new BranchGroup();
     
      Color3f darkColor    = new Color3f(0.0f, 0.0f, 0.0f);
      Color3f diffuColor  = new Color3f(0.6f, 0.0f, 0.0f);
      Material mat = new Material(darkColor, darkColor, diffuColor, darkColor, 0.0f);
      Appearance appear = new Appearance();
      appear.setMaterial(mat);
     
      Sphere sphere = new Sphere(0.5f, Sphere.GENERATE_NORMALS, 100, appear);
      group2.addChild(sphere);
      Color3f color = new Color3f(3.0f, 3.0f, 0.0f);
      BoundingSphere bounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), 1.0);
      Vector3f lightDirection = new Vector3f(-1.0f, -1.0f, -1.0f);
      DirectionalLight light   = new DirectionalLight(color, lightDirection);
      light.setInfluencingBounds(bounds);
      group2.addChild(light);
      group.addChild(group2);

      universe.getViewingPlatform().setNominalViewingTransform();
      group.compile();
      universe.addBranchGraph(group);
      getJContentPane().add(canvas);
   }
--------------------------------------------------------

ここで新しく出てきたAppearanceというのは、物体の見え方を表現するクラスで、
物体の見え方のうち、物体の色(正確に言うと光の反射や発光に関する性質)に
ついてはMaterialというクラスを通して設定することになっています。
というわけで、上のソース・コードでは

appear.setMaterial(mat);

というコードによって、Materialオブジェクト(ここではmatという変数名にしている)
をAppearanceオブジェクト(ここではappearという変数名にしている)に設定してい
ます。

そして、ここで新しく出てきたMaterialというのは、物体の材質を表現するクラスで、
3Dグラフィックスでは見え方にかかわる材質しか意味がないため、光にかかわる性質
だけを表現します。
上のソース・コードでは

Material mat = new Material(darkColor, darkColor, diffuColor, darkColor, 0.0f);

というコードでインスタンス生成していますが、このMaterialのコンストラクターの
第一引数は周辺光または環境光に反応する色を指定し、第二引数はその物体自体が
発光する場合の色を指定し、第三引数はその物体が光を乱反射するときの色を指定し、
第四引数にはその物体が光を鏡面反射(鏡や磨いた金属面のように決まった角度に光
を反射すること)するときの色を指定し、第五引数には輝きの度合いを指定します。

詳しいことはおいおい説明しますが、今回は乱反射の色だけを指定している(他のもの
はすべて0を指定している)ことに注目してください。

この乱反射の色(ここではdiffuColorという変数名にしている)はColor3f(0.6f, 0.0f, 0.0f)
で生成していますから、赤色です。

したがって、このソース・コードを保管して実行すると、球体が赤色に見えるはずです。


ところで、Appearanceオブジェクト(ここではappearという変数名にしている)は

Sphere sphere = new Sphere(0.5f, Sphere.GENERATE_NORMALS, 100, appear);

のようにSphereのコンストラクターの第四引数として設定できます。


もちろん、こういった設定作業はコンストラクター以外に、専用のメソッドを使って行う
こともできます。



では、今度は、乱反射の色をgreenに変えてみてください。つまり、diffuColorのインス
タンス生成のコードを

Color3f diffuColor  = new Color3f(0.0f, 0.6f, 0.0f);

に書き換えてみてください。


編集が終わったら、保管して実行してみてください。今度は球体が緑色に見えるはず
ですね。


では、次に、乱反射の色をblueに変えてみてください。つまり、diffuColorのインス
タンス生成のコードを

Color3f diffuColor  = new Color3f(0.0f, 0.0f, 0.6f);

に書き換えてみてください。


編集が終わったら、保管して実行してみてください。今度は球体が青色に見えるはず
  ・
  ・
  ・
  ・
  ・
  ・
  ・
  ・
  ・
  ・
  ・
なわけがありません。

照射した光がredとgreenの混合色(=黄色)ですから、blueの光は含んでいません。
したがって、球体がblueの光を反射したくても反射できないのです。

この場合、反射できる光がまったくないので、球体は真っ暗になってしまうの
です。



ところで、この球体は、光を反射(乱反射)して見えているときでも、光の影に
なっている部分は完全に真っ暗になっていますね。


通常、我々が太陽光の下で物体を見ているときは、日陰になっている部分も
(暗いけれどぼんやりと)見えているはずです。
これは、周囲の物体で乱反射した光や空気中で散乱された光が影の部分を
(うっすらと)照らすからです。

このような光を周辺光(ambient light)または環境光と呼びます。


(次回に続く)


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

何か、わからないところがありましたら、下記の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. 不許無断複製