Java3Dの光源と物体の表面属性を操作してみる

  • 投稿日:
  • by
  • カテゴリ:

Java3Dで物体に色を付けるには、光源と物体の表面属性を設定する必要がある訳だが、光源色と表面属性の色成分の関係がよくわからない。光源色を変えても色が変わらなかったり、物体表面の反射成分を変えても色が変わらなかったりする。いろんなパラメーターをいじって試しても、物体が真っ白のままで何が悪いのかさっぱり見当がつかないと、全く理解が進まない。筆者はもう1年以上わけがわからないままである。

そこで、光源色と物体の表面属性をスライドバーで操作できるアプレットを作ってみた。

光源/表面属性のテストアプレット
ソースコード

点光源が上の方を旋回しており、平行光源は左手前にあって右奥に向けている。2つの小さな円錐は、光源のおおよその位置を表している。

操作できるパラメーターを説明する。

●光源について
・環境光源(Ambient light)
 空間全体に万遍なく存在する光。影を作らない。
・平行光源(Directional light)
 ある一定の方向から全空間を等しく照射する光。
・点光源(Point light)
 ある一点から放射状に放たれる光。光源からの距離に応じて減衰する。

●物体の表面属性(材質、Material)について
・拡散反射成分(Diffuse color)
 入射角に関係なく全方向に反射させる色成分。
・鏡面反射成分(Specular color)
 入射角と反射角の大きさが等しい反射をさせる色成分。
・環境光反射成分(Ambient color)
 環境光を反射させる色成分。
・発光色(Emissive color)
 光源に関係なく、自ら発する光の色成分。
・つや(Shininess)
 鏡面反射の鋭さ。

大体、自然界と同じように、光源色の一部の成分が反射光となる感じである。白色光に対しては、赤色光のみを反射する物体は赤くなるし、緑色光のみを反射する物体は緑色になるが、青色光に対しては、赤色光や緑色光のみを反射する物体は光を反射せず黒くなる。

バーをスライドさせても物体が真っ白のまま変化しなくても、根気よくいろんなバーをスライドさせていれば、どれかを触った時にきっと色に変化が起こる。
どうやら有効なパラメーターはTarget colorによって変わるようであるが、まだ関係がよくわからない。そのうち、ちゃんと理屈を知ってからいじって理解しようと思う。今回はこれを作っただけで満足する。


今回のアプレットでは、Java3Dのシーングラフ(オブジェクトの木構造)を途中で変更している("Change shape"ボタン押下時)。それに関して調べたことを記録する。
・J3Dスレッドが使用中のシーングラフから削除できるノードはBranchGroupノードのみである。従って、後で切り離したいノードは切り離し用のBranchGroupノードの下に配置する必要がある。
・シーングラフを操作するためには、一度Universeから切り離す必要がある。そのため、シーングラフにはALLOW_DETACHを設定しておく。
・SimpleUniverseの場合、シーングラフのdetachは

SimpleUniverse#getLocale()#removeBranchGraph()
で行う。その後のattachは通常のSimpleUniverse#addBranchGraph()で良い。
・BranchGroupノードに繋がる子ノードを追加したり削除したりするためには、そのBranchGroupノードにALLOW_CHILDREN_WRITEを設定する必要がある。
・AppearanceやMaterialのインスタンスは、シーングラフをdetachせずに変更してもJ3Dの描画に反映されるようである。


今回は、スライドバーを使いたかったため、Java3DとSwingを組み合わせて作った。Java3DとSwingは相性が悪いというようなことをどこかで読んだ記憶かあるが、今回はそれほど問題は起こらなかった。
ただ、スライドバーのイベントリスナー内でJava3Dのシーングラフのattachとdetachをしていると、スライドバーを素早く動かすとアプレットが固まってしまうことがわかった。

SimpleUniverse.setJ3DThreadPriority(Thread.MIN_PRIORITY);
としてJava3Dの優先度を下げると改善したが、完全には治らなかった。SwingUtilities.invokeLater()を使えば良いのかも知れないが、根本原因がわからないので、それで解決するのかどうかわからない。

以前にJava3Dがインストールされていない環境でも実行できるようにJava3Dのアプレットを公開する方法として
org.jdesktop.applet.util.JNLPAppletLauncherを介する方法のことを書いたが、その後、JREにJNLPが内蔵されJRE 6u10以降)、きれいにJava3Dが起動できるようになったようである。しかし、そのようなJREはまだ普及していないと思うし、そもそも筆者が普段使用しているMacの環境ではJNLPは動かなかった。そのため、今回は、JNLPが内蔵されていればそれで、内蔵されていなければJNLPAppletLauncherを使うようにした。

・HTMLに書いたもの

<applet code="org.jdesktop.applet.util.JNLPAppletLauncher"
width=800 height=600
archive="LightTest2.jar,
http://download.java.net/media/applet-launcher/applet-launcher.jar,
http://download.java.net/media/java3d/webstart/release/j3d/latest/j3dcore.jar,
http://download.java.net/media/java3d/webstart/release/j3d/latest/j3dutils.jar,
http://download.java.net/media/jogl/builds/archive/jsr-231-webstart-current/jogl.jar,
http://download.java.net/media/gluegen/webstart/gluegen-rt.jar,
http://download.java.net/media/java3d/webstart/release/vecmath/latest/vecmath.jar">
<param name="codebase_lookup" value="false">
<param name="subapplet.classname" value="LightTest2">
<param name="subapplet.displayname" value="My Java 3D Applet">
<param name="jnlpNumExtensions" value="1">
<param name="jnlpExtension1" value="http://download.java.net/media/java3d/webstart/release/java3d-latest.jnlp">
<param name="progressbar" value="true">
<param name="noddraw.check" value="true">
<param name="jnlp_href" value="lighttest2.jnlp">

Maybe Java functionality is disabled.
</applet>
・lighttest2.jnlpの中身
<?xml version="1.0" encoding="utf-8"?>
<jnlp codebase="http://ynomura.dip.jp/java/" href="lighttest2.jnlp">
<information>
<title>Lighting test 2</title>
<vendor>ynomura.dip.jp</vendor>
<homepage href="http://ynomura.dip.jp/"/>
<description kind="short">Lighting test with slidebar</description>
<offline-allowed/>
</information>
<resources>
<j2se version="1.5+"/>
<property name="sun.java2d.noddraw" value="true"/>
<jar href="LightTest2.jar" main="true"/>
<extension name="java3d-latest" href="http://download.java.net/media/java3d/webstart/release/java3d-latest.jnlp"/>
</resources>
<applet-desc
name="LightTest2"
main-class="LightTest2"
width="800"
height="600">
</applet-desc>
</jnlp>

参考:http://forums.sun.com/thread.jspa?threadID=5401999

便利になったはずが、当面かなり不便である。