四面体を描画

三角形ポリゴンを組み合わせて四面体を描画します。
四面体の面に色を設定します。
メソッドを使って四面体に法線ベクトルを設定します。

Applet でプログラムを体験できます。
四面体の面に色を設定する

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

プログラムの作成

  1. 三角形ポリゴンを組み合わせて四面体を描画します。
    メモ帳などでタイプして Men4.java の名前で保存して下さい。
    //★ 四面体を生成してマウスで操作する    前田 稔
    import java.awt.*;
    import javax.swing.*;
    import javax.media.j3d.*;
    import javax.vecmath.*;
    import com.sun.j3d.utils.universe.*;
    import com.sun.j3d.utils.behaviors.mouse.MouseRotate;
    import com.sun.j3d.utils.behaviors.mouse.MouseTranslate;
    import com.sun.j3d.utils.behaviors.mouse.MouseZoom;
    
    // Main Class
    public class Men4 extends JFrame
    {
        // main Method
        public static void main(String[] args)
        {   new Men4();  }
    
        // Constructor
        public Men4()
        {   // JFrame の初期化
            super("4 Mentai");
            setSize(300,300);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            // 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(CreateScene());
    
            // JFrame を表示
            setVisible(true);
        }
    
        // 三角ポリゴンで四面体を生成
        private BranchGroup CreateScene()
        {   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)
            };
    
            // 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);
    
            // 四面体を生成
            TriangleArray geometry = new TriangleArray(vertices.length, GeometryArray.COORDINATES);
            geometry.setCoordinates(0, vertices);
    
            // BranchGroup に登録
            Shape3D shape = new Shape3D(geometry);
            trans.addChild(shape);
            objRoot.addChild(trans);
            return objRoot;
        }
    }
    
  2. ソースプログラムをコンパイルして class オブジェクトを実行して下さい。
    四面体がシルエット(白色)で描画されます。
    マウスの左ボタンを押しながらドラッグすると四面体が回転します。
    マウスの右ボタンを押しながらドラッグすると四面体が移動します。
    マウスの中央ボタンを押しながらドラッグすると四面体がズームイン・ズームアウトします。

説明

  1. このプログラムは CreateScene() メソッド以外は Point.java と同じ要領です。
    基本的な説明は Java 3D で点を描画 を参照して下さい。
    マウスを使うので Mouse 関係のライブラリを import します。
        import java.awt.*;
        import javax.swing.*;
        import javax.media.j3d.*;
        import javax.vecmath.*;
        import com.sun.j3d.utils.universe.*;
        import com.sun.j3d.utils.behaviors.mouse.MouseRotate;
        import com.sun.j3d.utils.behaviors.mouse.MouseTranslate;
        import com.sun.j3d.utils.behaviors.mouse.MouseZoom;
        
  2. 四個の三角ポリゴンで四面体を定義する CreateScene() メソッドです。
    BranchGroup を生成して、ここに描画するシーンを設定します。
    Point3d[] で四面体を構成する三角ポリゴンの頂点座標を定義します。
    Window の座標系と三次元座標系では、向きが異なります。
        // 三角ポリゴンで四面体を生成
        private BranchGroup CreateScene()
        {   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)
            };
        
  3. 四面体を正面から見たのでは、三角形にしか見えません。
    そこでマウスを使って四面体を操作してみましょう。
    new TransformGroup() で座標変換のオブジェクトを生成します。
    オブジェクトに setCapability() で ALLOW_TRANSFORM_READ と ALLOW_TRANSFORM_WRITE を許可して下さい。
    BoundingSphere でマウス操作の及ぶ範囲を設定します。
    モデルの回転を設定します。
    モデルの移動を設定します。
    モデルのズームを設定します。
    後は何も書かなくても、これだけでマウスでモデルを操作できるようになります。
            // 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);
        
  4. new TriangleArray() で四面体を構成するポリゴンを生成します。
    new Shape3D(geometry); で TriangleArray を引数にして Shape3D を生成します。
    TransformGroup に Shape3D を追加します。
    これで四面体をマウスで操作出来るようになります。
    BranchGroup に TransformGroup を追加します。
            // 四面体を生成
            TriangleArray geometry = new TriangleArray(vertices.length, GeometryArray.COORDINATES);
            geometry.setCoordinates(0, vertices);
    
            // BranchGroup に登録
            Shape3D shape = new Shape3D(geometry);
            trans.addChild(shape);
            objRoot.addChild(trans);
            return objRoot;
        }
        

色を設定

  1. 四面体が描画出来たのは良いのですが、シルエット(白色)だけでは立体に見えません。
    そこで、各面に色を設定して描画してみましょう。
  2. CreateScene() メソッドを次のように修正し下さい。
    Point3d[] は前と同じですが、Color3f[] でポリゴンの頂点座標の色を定義します。
    各面ごとに色を設定するので、三角形ポリゴンに合わせて3個ずつ対になっています。
        // 三角ポリゴンで四面体を生成
        private BranchGroup CreateScene()
        {   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)
            };
    
            // ポリゴンの頂点座標の色を定義
            Color3f[] colors =
            {  new Color3f(1.0f, 0.0f, 0.0f), new Color3f(1.0f, 0.0f, 0.0f), new Color3f(1.0f, 0.0f, 0.0f),   // red
               new Color3f(0.0f, 1.0f, 0.0f), new Color3f(0.0f, 1.0f, 0.0f), new Color3f(0.0f, 1.0f, 0.0f),   // green
               new Color3f(0.0f, 0.0f, 1.0f), new Color3f(0.0f, 0.0f, 1.0f), new Color3f(0.0f, 0.0f, 1.0f),   // blue
               new Color3f(1.0f, 1.0f, 0.0f), new Color3f(1.0f, 1.0f, 0.0f), new Color3f(1.0f, 1.0f, 0.0f) }; // yellow
        
  3. 四面体をマウスで操作する方法は前と同じです。
            // Model の修正を許可
            TransformGroup trans = new TransformGroup();
                ・・・
            objRoot.addChild(zoomer);
        
  4. 四面体を構成する三角形ポリゴンを生成します。
    頂点に色を設定するので、フラグに GeometryArray.COLOR_3 を追加して下さい。
    geometry.setColors(0, colors); で頂点に色を設定します。
    new Shape3D(geometry); で TriangleArray を引数にして Shape3D を生成します。
    TransformGroup に Shape3D を追加します。
    BranchGroup に TransformGroup を追加します。
            // 四面体を生成
            //TriangleArray geometry = new TriangleArray(vertices.length, GeometryArray.COORDINATES);
            TriangleArray geometry = new TriangleArray(vertices.length, GeometryArray.COORDINATES | GeometryArray.COLOR_3);
            geometry.setCoordinates(0, vertices);
            geometry.setColors(0, colors);
    
            // BranchGroup に登録
            Shape3D shape = new Shape3D(geometry);
            trans.addChild(shape);
            objRoot.addChild(trans);
            return objRoot;
        }
        

法線ベクトルの計算

  1. 各面に色は設定されたのですが立体感に欠けるでしょう。
    立体的に見せるには、ライトで照らして「光と影」を演出しなければなりません。
    物体は光を反射してその姿が見えるのですが、強く光を反射する方向を法線ベクトルで設定します。
    法線ベクトルの説明は 前田稔の超初心者のプログラム入門 から「DirectX9/マテリアルを設定して、虎のモデルを描画する」を参照して下さい。
  2. CreateScene() メソッドを次のように修正し下さい。
    DirectionalLight() で平行光源を設定します。
    光源には「環境光/平行光源/点光源/スポットライト」があります。
    new BoundingSphere(new Point3d(),100.0); で光源が作用する範囲を設定します。
    Color3f(1.0f,1.0f,1.0f) は光源の色(白)で、Vector3f(0.3f,-0.3f,-0.3f) は光源の向きです。
    向きは 0.3f:やや右方向を、-0.3f:やや下向きに、-0.3f:やや奥方向を照らします。
    ちなみに Vector3f(0.0f, 0.0f, -1.0f) で正面から、new Vector3f(0.87f, 0.0f, -0.5f) で斜め左方向から照明があたります。
    AmbientLight() は環境光の設定で、Light に照らされない部分を薄暗くします。
    四面体の座標定義 や Mouse 操作の設定は前と同じです。
        //  三角ポリゴンで四面体を生成
        private BranchGroup CreateScene()
        {   BranchGroup objRoot = new BranchGroup();
    
            // 四面体の頂点座標を定義
                ・・・
    
            // 平行光源の設定の設定
            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);
    
            // Mouse 操作の設定
                ・・・
        
  3. 四面体を構成する三角形ポリゴンを生成します。
    FaceNormals(vertices); が法線ベクトルを計算するメソッドです。
    頂点に法線ベクトルを設定するので、フラグに GeometryArray.NORMALS を追加して下さい。
    geometry.setNormals(0, normals); で頂点に法線ベクトルを設定します。
    new Shape3D(geometry); で geometry を引数にして Shape3D を生成します。
    shape.setAppearance(createAppearance()) で、マテリアルを設定した Appearance を生成します。
    TransformGroup に Shape3D を追加します。
    BranchGroup に TransformGroup を追加します。
            // 四面体を生成
            Vector3f[] normals = FaceNormals(vertices);
            TriangleArray geometry =
                new TriangleArray(vertices.length, GeometryArray.COORDINATES | GeometryArray.NORMALS);
            geometry.setCoordinates(0, vertices);
            geometry.setNormals(0, normals);
    
            // Material を設定して BranchGroup に追加
            Shape3D shape = new Shape3D(geometry);
            shape.setAppearance(createAppearance());
            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;
        }
        
  5. 法線ベクトルを計算する FaceNormals() メソッドです。
    Point3d[] vertices が三角形ポリゴンの座標を定義した配列です。
    光が強く反射する方向は三角形ポリゴンの向きに対して直角の方向です。
        // 法線配列の設定
        private Vector3f[] FaceNormals(Point3d[] vertices)
        {   Vector3f[] normals = new Vector3f[vertices.length];
    
            for (int i=0; i<vertices.length; i+=3)
            {   Vector3f fnormal = FaceNormal(i, vertices);
                normals[i] = fnormal;
                normals[i+1] = fnormal;
                normals[i+2] = fnormal;
            }
            return normals;
        }
    
        // 法線の計算
        private Vector3f FaceNormal(int index, Point3d[] vertices)
        {   double ax = vertices[index + 2].x - vertices[index + 1].x;
            double ay = vertices[index + 2].y - vertices[index + 1].y;
            double az = vertices[index + 2].z - vertices[index + 1].z;
            double bx = vertices[index + 0].x - vertices[index + 1].x;
            double by = vertices[index + 0].y - vertices[index + 1].y;
            double bz = vertices[index + 0].z - vertices[index + 1].z;
    
            double nx = ay * bz - az * by;
            double ny = az * bx - ax * bz;
            double nz = ax * by - ay * bx;
    
            Vector3f normal = new Vector3f((float)nx, (float)ny, (float)nz);
            normal.normalize();
            return  normal;
        }
        

超初心者のプログラム入門(Java2)