四面体に法線ベクトルを設定する

四面体に法線ベクトルを設定してライトで照らして描画します。

Java Applet の実行は、次のリンクをクリックして下さい。
四面体に法線ベクトルを設定する

前田稔の超初心者のプログラム入門

プログラムの作成

  1. メモ帳などでタイプして applet_normal.java の名前で保存して下さい。
    //★ 四面体に法線ベクトルを設定する    前田 稔
    import java.applet.Applet;
    import java.awt.*;
    import javax.swing.*;
    import javax.media.j3d.*;
    import javax.vecmath.*;
    import com.sun.j3d.utils.universe.*;
    import com.sun.j3d.utils.applet.MainFrame;
    import com.sun.j3d.utils.behaviors.mouse.*;
    import com.sun.j3d.utils.geometry.*;
    
    public class applet_normal extends Applet
    {
        // main Method
        public static void main(String[] args)
        {   new MainFrame(new applet_normal(), 300, 300);  }
    
        // Constructor
        public applet_normal() {  }
    
        // Applet 初期化
        public void init()
        {   setLayout(new BorderLayout());
    
            // Java3D関係の設定
            GraphicsConfiguration g_config = SimpleUniverse.getPreferredConfiguration();
            Canvas3D canvas = new Canvas3D(g_config);
            add(canvas);
    
            // SimpleUniverseを生成
            SimpleUniverse universe = new SimpleUniverse(canvas);
            universe.getViewingPlatform().setNominalViewingTransform();
    
            // シーンの生成
            universe.addBranchGraph(createSceneGraph());
            setVisible(true);
        }
    
        //  三角ポリゴンで四面体を生成
        private BranchGroup createSceneGraph()
        {   BranchGroup objRoot = new BranchGroup();
    
            // 四面体の座標を定義
            Point3d[] vertices =
            {  new Point3d(0.0, 0.0, -0.4), new Point3d(0.0, 0.8, 0.2),  new Point3d(0.5, 0.0, 0.5),
               new Point3d(0.0, 0.0, -0.4), new Point3d(-0.5, 0.0, 0.5), new Point3d(0.0, 0.8, 0.2),
               new Point3d(0.0, 0.0, -0.4), new Point3d(0.5, 0.0, 0.5),  new Point3d(-0.5, 0.0, 0.5),
               new Point3d(0.5, 0.0,  0.5), new Point3d(0.0, 0.8, 0.2),  new Point3d(-0.5, 0.0, 0.5)
            };
    
            // Light の設定
            BoundingSphere bounds = new BoundingSphere(new Point3d(),100.0);
            DirectionalLight dlight =
                new DirectionalLight(true, new Color3f(1.0f,1.0f,1.0f), new Vector3f(0.3f,-0.3f,-0.3f));
            dlight.setInfluencingBounds(bounds);
            objRoot.addChild(dlight);
            AmbientLight alight = new AmbientLight();
            alight.setInfluencingBounds(bounds);
            objRoot.addChild(alight);
    
            // Model の修正を許可
            TransformGroup trans = new TransformGroup();
            trans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
            trans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
    
            // 回転を設定
            //BoundingSphere bounds = new BoundingSphere(new Point3d(), 100.0);
            MouseRotate rotator = new MouseRotate(trans);
            rotator.setSchedulingBounds(bounds);
            objRoot.addChild(rotator);
    
            // 移動を設定
            MouseTranslate translator = new MouseTranslate(trans);
            translator.setSchedulingBounds(bounds);
            objRoot.addChild(translator);
    
            // ズームを設定
            MouseZoom zoomer = new MouseZoom(trans);
            zoomer.setSchedulingBounds(bounds);
            objRoot.addChild(zoomer);
    
            // 四面体を作成
            GeometryInfo ginfo = new GeometryInfo(GeometryInfo.TRIANGLE_ARRAY);
            ginfo.setCoordinates(vertices);
    
            // 法線ベクトルの設定
            NormalGenerator gen = new NormalGenerator();
            gen.generateNormals(ginfo);
    
            // Material を設定して BranchGroup に追加
            Shape3D shape = new Shape3D(ginfo.getGeometryArray());
            shape.setAppearance(createAppearance());
    
            // BranchGroup に登録
            trans.addChild(shape);
            objRoot.addChild(trans);
            return objRoot;
        }
    
        // Material の設定
        private Appearance createAppearance()
        {   Material mat = new Material();
            // デフォルト値
            mat.setLightingEnable(true);            // 照明が有効
            mat.setAmbientColor(0.2f, 0.2f, 0.2f);  // 環境光による色は   濃いグレー
            mat.setEmissiveColor(0.0f, 0.0f, 0.0f); // 発光による色は     黒(発光しない)
            mat.setDiffuseColor(1.0f, 1.0f, 1.0f);  // 拡散反射による色は 白
            mat.setSpecularColor(1.0f, 1.0f, 1.0f); // 鏡面反射による色は 白
            mat.setShininess(64.0f);                // 輝度は             64(中間値)
    
            mat.setDiffuseColor(new Color3f(0.8f, 0.8f, 0.0f));
            Appearance ap = new Appearance();
            ap.setMaterial(mat);
            return ap;
        }
    }
    
  2. Java Applet を起動する HTMLファイルは、何時もと同じです。
    ソースプログラムをコンパイルして class オブジェクトを実行して下さい。
    Java Applet を使ったプログラムですが、コマンドラインから普通の Java と同様に実行することが出来ます。
    アプレットの実行は HTMLファイルをダブルクリックして起動して下さい。
    アプレットを実行しようとするとセキュリティの警告画面が表示されますが、解除して下さい。

プログラムの説明

  1. 法線ベクトルの設定を除いて「四面体の面に色を設定する」と同じ要領です。
    基本的な説明は 四面体の面に色を設定する を参照して下さい。
    「四面体の面に色を設定する」では各面に色は設定されたのですが立体感に欠けるでしょう。
    立体的に見せるには、ライトで照らして「光と影」を演出しなければなりません。
    物体は光を反射してその姿が見えるのですが、強く光を反射する方向を法線ベクトルで設定します。
    法線ベクトルの説明は 前田稔の超初心者のプログラム入門 から「DirectX9/マテリアルを設定して、虎のモデルを描画する」を参照して下さい。
  2. Point3d[] は前と同じです。
    DirectionalLight() で平行光源を設定します。
    光源の説明は 四面体を描画 を参照して下さい。
    マウスでモデルを操作する設定は前と同じです。
        //  三角ポリゴンで四面体を生成
        private BranchGroup createSceneGraph()
        {   BranchGroup objRoot = new BranchGroup();
    
            // 四面体の座標を定義
            Point3d[] vertices =
            {  new Point3d(0.0, 0.0, -0.4), new Point3d(0.0, 0.8, 0.2),  new Point3d(0.5, 0.0, 0.5),
               new Point3d(0.0, 0.0, -0.4), new Point3d(-0.5, 0.0, 0.5), new Point3d(0.0, 0.8, 0.2),
               new Point3d(0.0, 0.0, -0.4), new Point3d(0.5, 0.0, 0.5),  new Point3d(-0.5, 0.0, 0.5),
               new Point3d(0.5, 0.0,  0.5), new Point3d(0.0, 0.8, 0.2),  new Point3d(-0.5, 0.0, 0.5)
            };
    
            // Light の設定
            BoundingSphere bounds = new BoundingSphere(new Point3d(),100.0);
            DirectionalLight dlight =
                new DirectionalLight(true, new Color3f(1.0f,1.0f,1.0f), new Vector3f(0.3f,-0.3f,-0.3f));
            dlight.setInfluencingBounds(bounds);
            objRoot.addChild(dlight);
            AmbientLight alight = new AmbientLight();
            alight.setInfluencingBounds(bounds);
            objRoot.addChild(alight);
    
            // Model の修正を許可
            TransformGroup trans = new TransformGroup();
            trans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
            trans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
    
            // 回転を設定
            //BoundingSphere bounds = new BoundingSphere(new Point3d(), 100.0);
            MouseRotate rotator = new MouseRotate(trans);
            rotator.setSchedulingBounds(bounds);
            objRoot.addChild(rotator);
    
            // 移動を設定
            MouseTranslate translator = new MouseTranslate(trans);
            translator.setSchedulingBounds(bounds);
            objRoot.addChild(translator);
    
            // ズームを設定
            MouseZoom zoomer = new MouseZoom(trans);
            zoomer.setSchedulingBounds(bounds);
            objRoot.addChild(zoomer);
        
  3. 四面体を構成する三角形ポリゴンを生成して法線ベクトルを設定します。
    new GeometryInfo(GeometryInfo.TRIANGLE_ARRAY) を生成します。
    NormalGenerator を生成して generateNormals(ginfo); で法線ベクトルを設定します。
    法線ベクトルを設定する最も簡単な方法です。
    new Shape3D(ginfo.getGeometryArray()); で GeometryInfo を引数にして Shape3D を生成します。
    shape.setAppearance(createAppearance()) で、マテリアルを設定した Appearance を生成します。
    TransformGroup に Shape3D を追加します。
    BranchGroup に TransformGroup を追加します。
            // 四面体を作成
            GeometryInfo ginfo = new GeometryInfo(GeometryInfo.TRIANGLE_ARRAY);
            ginfo.setCoordinates(vertices);
    
            // 法線ベクトルの設定
            NormalGenerator gen = new NormalGenerator();
            gen.generateNormals(ginfo);
    
            // Material を設定して BranchGroup に追加
            Shape3D shape = new Shape3D(ginfo.getGeometryArray());
            shape.setAppearance(createAppearance());
    
            // BranchGroup に登録
            trans.addChild(shape);
            objRoot.addChild(trans);
            return objRoot;
        }
        
  4. Appearance を生成する createAppearance() メソッドです。
    モデルに色や光沢など Material を設定します。
    マテリアルの説明は 前田稔の超初心者のプログラム入門 から「DirectX9/球をライトで照らして View 座標を回転する」を参照して下さい。
    setDiffuseColor() がモデルの色で、赤・緑・青の順に 0.0〜1.0 の範囲で設定します。
    モデルの色を変えて試してみて下さい。
        // Material の設定
        private Appearance createAppearance()
        {   Material mat = new Material();
            // デフォルト値
            mat.setLightingEnable(true);            // 照明が有効
            mat.setAmbientColor(0.2f, 0.2f, 0.2f);  // 環境光による色は   濃いグレー
            mat.setEmissiveColor(0.0f, 0.0f, 0.0f); // 発光による色は     黒(発光しない)
            mat.setDiffuseColor(1.0f, 1.0f, 1.0f);  // 拡散反射による色は 白
            mat.setSpecularColor(1.0f, 1.0f, 1.0f); // 鏡面反射による色は 白
            mat.setShininess(64.0f);                // 輝度は             64(中間値)
    
            mat.setDiffuseColor(new Color3f(0.8f, 0.8f, 0.0f));
            Appearance ap = new Appearance();
            ap.setMaterial(mat);
            return ap;
        }
        

Java Game Program