立方体の各面に色を設定して、3面にアルファチャネルテクスチャを貼り付けます。

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

プログラムの作成

  1. 立方体の各面に色を設定して、3面にアルファチャネルテクスチャを貼り付けます。
    メモ帳などでタイプして BoxAlphaBMP.java の名前で保存して下さい。
    //★ Alpha Cannel 付きテクスチャを貼り付ける    前田 稔
    import java.awt.*;
    import javax.swing.*;
    import java.io.*;
    import java.awt.image.*;
    import javax.imageio.ImageIO;
    import javax.media.j3d.*;
    import javax.vecmath.*;
    import com.sun.j3d.utils.universe.*;
    import com.sun.j3d.utils.behaviors.mouse.*;
    import com.sun.j3d.utils.geometry.*;
    import com.sun.j3d.utils.image.TextureLoader;
    
    // Main Class
    public class BoxAlphaBMP extends JFrame
    {
        // main Method
        public static void main(String[] args)
        {   new BoxAlphaBMP();  }
    
        // Constructor
        public BoxAlphaBMP()
        {   // JFrame の初期化
            super("Alpha Texture");
            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());
            setVisible(true);
        }
    
        // 立方体を生成
        private BranchGroup CreateScene()
        {   BranchGroup objRoot = new BranchGroup();
    
            // 頂点座標
            Point3d[] vertices =
            {  new Point3d(-0.5, 0.5, 0.5),  new Point3d(-0.5, -0.5, 0.5),  //左上前,  左下前
               new Point3d(0.5, -0.5, 0.5),  new Point3d(0.5, 0.5, 0.5),    //右下前,  右上前
               new Point3d(-0.5, 0.5, -0.5), new Point3d(-0.5, -0.5, -0.5), //左上奥,  左下奥
               new Point3d(0.5, -0.5, -0.5), new Point3d(0.5, 0.5, -0.5)    //右下奥,  右上奥
            };
    
            // 法線ベクトル
            Vector3f[] normals =
            {  new Vector3f(0.0f, 0.0f, 1.0f), new Vector3f(-1.0f, 0.0f, 0.0f), //前面, 左面
               new Vector3f(0.0f, 1.0f, 0.0f), new Vector3f(1.0f, 0.0f, 0.0f),  //上面, 右面
               new Vector3f(0.0f, 0.0f, -1.0f),new Vector3f(0.0f, -1.0f, 0.0f)};//奥面, 底面
    
            // テクスチャの座標を定義
            TexCoord2f[] texture =
            {  new TexCoord2f(0.0f, 0.0f),  new TexCoord2f(1.0f, 0.0f),   // 左下,  右下
               new TexCoord2f(1.0f, 1.0f),  new TexCoord2f(0.0f, 1.0f)    // 右上,  左上
            };
    
            // 頂点座標の色を定義
            Color3f[] colors =
            {  new Color3f(0.0f,1.0f,0.0f), new Color3f(0.0f,0.0f,1.0f), new Color3f(1.0f,1.0f,0.0f)  };
    
            // Index を定義
            int[] idx1  = {  0,1,2,3,  4,5,1,0,  4,0,3,7  };    //前面, 左面, 上面
            int[] idx2  = {  7,6,5,4,  3,2,6,7,  1,5,6,2  };    //奥面, 右面, 底面
            int[] vidx1 = {  0,0,0,0,  1,1,1,1,  2,2,2,2  };
            int[] vidx2 = {  3,3,3,3,  4,4,4,4,  5,5,5,5  };
            int[] tidx1 = {  0,1,2,3,  0,1,2,3,  0,1,2,3  };
            int[] tidx2 = {  0,1,2,3,  0,1,2,3,  0,1,2,3  };
            int[] cidx1 = {  0,0,0,0,  1,1,1,1,  2,2,2,2  };
            int[] cidx2 = {  0,0,0,0,  1,1,1,1,  2,2,2,2  };
    
            // 矩形の区切りを定義(4角形ポリゴン*3*2)
            int[] stripCount = { 4,4,4 };
    
            // 平行光源の設定
            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 操作の設定
            TransformGroup trans = new TransformGroup();
            SetMouse(objRoot, trans);
    
            //※ 立方体の3面を作成
            GeometryInfo ginfo = new GeometryInfo(GeometryInfo.POLYGON_ARRAY);
            ginfo.setCoordinates(vertices);
            ginfo.setCoordinateIndices(idx1);
            ginfo.setStripCounts(stripCount);
            ginfo.setNormals(normals);
            ginfo.setNormalIndices(vidx1);
    
            // Color の設定
            ginfo.setColors(colors);
            ginfo.setColorIndices(cidx1);
    
            // Material を設定して BranchGroup に追加
            Shape3D shape = new Shape3D(ginfo.getGeometryArray());
            shape.setAppearance(createAppearance(0));
            trans.addChild(shape);
    
            //※ テクスチャを張り付けた3面を作成
            GeometryInfo ginfo2 = new GeometryInfo(GeometryInfo.POLYGON_ARRAY);
            ginfo2.setCoordinates(vertices);
            ginfo2.setCoordinateIndices(idx2);
            ginfo2.setStripCounts(stripCount);
            ginfo2.setNormals(normals);
            ginfo2.setNormalIndices(vidx2);
    
            // Color の設定
            ginfo2.setColors(colors);
            ginfo2.setColorIndices(cidx2);
    
            // Texture の設定
            ginfo2.setTextureCoordinateParams(1,2);
            ginfo2.setTextureCoordinates(0,texture);
            ginfo2.setTextureCoordinateIndices(0,tidx2);
    
            // Material を設定して BranchGroup に追加
            Shape3D shape2 = new Shape3D(ginfo2.getGeometryArray());
            shape2.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
            shape2.setAppearance(createAppearance(1));
            trans.addChild(shape2);
    
            objRoot.addChild(trans);
            return objRoot;
        }
    
        // Material の設定
        private Appearance createAppearance(int flag)
        {
            Appearance app = new Appearance();
            if (flag==1)
            {   BufferedImage bimage = loadAlpha("C:\\DATA\\Test\\Kishi32.bmp");
                TextureLoader texload = new TextureLoader(bimage);
                Texture2D texture2d = (Texture2D)texload.getTexture();
                app.setTexture(texture2d);
                //※ 透明度の設定
                app.setTransparencyAttributes(new TransparencyAttributes(TransparencyAttributes.BLENDED, 0.0f));
                // テクスチャ属性
                TextureAttributes txattr = new TextureAttributes();
                txattr.setTextureMode(TextureAttributes.DECAL);
                app.setTextureAttributes(txattr);
            }
            return app;
        }
    
        // Mouse 操作の設定
        public void SetMouse(BranchGroup objRoot, TransformGroup trans)
        {
            // Model の修正を許可
            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);
        }
    
        // Alpha Cannel Image の入力
        public static BufferedImage loadAlpha(String fileName)
        {   BufferedImage img= null;
            int     width;
            int     height;
            int     len;
            byte[]  buf = new byte[64];
    
            try
            {   InputStream in = new FileInputStream(fileName);
                BufferedInputStream bin = new BufferedInputStream(in);
    
                // BITMAPFILEHEADER を入力
                if ((len= bin.read(buf, 0, 14))==-1)    return null;
                if (buf[0]!='B' || buf[1]!='M')     return img; // BMP以外
    
                // BITMAPINFOHEADER を入力
                if ((len= bin.read(buf, 0, 40))==-1)    return null;
                width= byte2int(buf, 4);
                height= byte2int(buf, 8);
                int  biBitCount= (buf[14]&0xFF) | ((buf[15]<<8)&0xFF00);
                if (biBitCount!=32) return null;        // 32bit以外
                int ary[] = new int[width * height];
                byte bt[] = new byte[width * height * 4];
                if ((len= bin.read(bt, 0, width*height*4))==-1) return null;
                bin.close();
                img= new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
                cvt(bt, ary);
                for(int y=0; y<height; y++)
                {   for(int x=0; x<width; x++)
                    {   img.setRGB(x, height-y-1, ary[y*width+x]);  }
                }
            }
            catch(Exception e) { }
            return img;
        }
    
        // byte[] ⇒ int[] 変換
        public static void cvt(byte[] bt, int ary[])
        {   for(int i=0; i<ary.length; i++)
                ary[i]= byte2int(bt, i*4);
        }
    
        // byte[] ⇒ int 変換
        public static int byte2int(byte[] buf, int p)
        {   return (buf[p]&0xFF) | ((buf[p+1]<<8)&0xFF00) | ((buf[p+2]<<16)&0xFF0000) | ((buf[p+3]<<24)&0xFF000000);
        }
    }
    
  2. アルファチャネル付きの BMP 画像を入力して、テクスチャとして貼り付けます。
    立方体の各面に色を設定しているので、テクスチャの透明部分から透けて見えます。

プログラムの説明

  1. GeometryInfo で立方体の各面に色を設定して、3面にアルファチャネル付きのテクスチャを貼り付けます。
    アルファチャネル付きの画像の説明は アルファチャネル付き画像をロード を参照して下さい。
  2. 立方体の座標(頂点, 法線, テクスチャ, 色)を定義します。
            // 頂点座標
            Point3d[] vertices =
            {  new Point3d(-0.5, 0.5, 0.5),  new Point3d(-0.5, -0.5, 0.5),  //左上前,  左下前
               new Point3d(0.5, -0.5, 0.5),  new Point3d(0.5, 0.5, 0.5),    //右下前,  右上前
               new Point3d(-0.5, 0.5, -0.5), new Point3d(-0.5, -0.5, -0.5), //左上奥,  左下奥
               new Point3d(0.5, -0.5, -0.5), new Point3d(0.5, 0.5, -0.5)    //右下奥,  右上奥
            };
    
            // 法線ベクトル
            Vector3f[] normals =
            {  new Vector3f(0.0f, 0.0f, 1.0f), new Vector3f(-1.0f, 0.0f, 0.0f), //前面, 左面
               new Vector3f(0.0f, 1.0f, 0.0f), new Vector3f(1.0f, 0.0f, 0.0f),  //上面, 右面
               new Vector3f(0.0f, 0.0f, -1.0f),new Vector3f(0.0f, -1.0f, 0.0f)};//奥面, 底面
    
            // テクスチャの座標を定義
            TexCoord2f[] texture =
            {  new TexCoord2f(0.0f, 0.0f),  new TexCoord2f(1.0f, 0.0f),   // 左下,  右下
               new TexCoord2f(1.0f, 1.0f),  new TexCoord2f(0.0f, 1.0f)    // 右上,  左上
            };
    
            // 頂点座標の色を定義
            Color3f[] colors =
            {  new Color3f(0.0f,1.0f,0.0f), new Color3f(0.0f,0.0f,1.0f), new Color3f(1.0f,1.0f,0.0f)  };
        
  3. Index の定義です。
    立方体を三面ずつ二つに分けて生成しています。
            // Index を定義
            int[] idx1  = {  0,1,2,3,  4,5,1,0,  4,0,3,7  };    //前面, 左面, 上面
            int[] idx2  = {  7,6,5,4,  3,2,6,7,  1,5,6,2  };    //奥面, 右面, 底面
            int[] vidx1 = {  0,0,0,0,  1,1,1,1,  2,2,2,2  };
            int[] vidx2 = {  3,3,3,3,  4,4,4,4,  5,5,5,5  };
            int[] tidx1 = {  0,1,2,3,  0,1,2,3,  0,1,2,3  };
            int[] tidx2 = {  0,1,2,3,  0,1,2,3,  0,1,2,3  };
            int[] cidx1 = {  0,0,0,0,  1,1,1,1,  2,2,2,2  };
            int[] cidx2 = {  0,0,0,0,  1,1,1,1,  2,2,2,2  };
    
            // 矩形の区切りを定義(4角形ポリゴン*3*2)
            int[] stripCount = { 4,4,4 };
        
  4. 緑, 青, 黄の色を設定した立方体の3面分を生成します。
    createAppearance(0) で flag にゼロを渡して、テクスチャの設定をパスします。
            //※ 立方体の3面を作成
            GeometryInfo ginfo = new GeometryInfo(GeometryInfo.POLYGON_ARRAY);
            ginfo.setCoordinates(vertices);
            ginfo.setCoordinateIndices(idx1);
            ginfo.setStripCounts(stripCount);
            ginfo.setNormals(normals);
            ginfo.setNormalIndices(vidx1);
    
            // Color の設定
            ginfo.setColors(colors);
            ginfo.setColorIndices(cidx1);
    
            // Material を設定して BranchGroup に追加
            Shape3D shape = new Shape3D(ginfo.getGeometryArray());
            shape.setAppearance(createAppearance(0));
            trans.addChild(shape);
        
  5. テクスチャを張り付けた残りの3面分を生成します。
    createAppearance(1) でテクスチャを設定します。
    テクスチャ属性を設定するので Shape3D の ALLOW_GEOMETRY_READ を許可して下さい。
            //※ テクスチャを張り付けた3面を作成
            GeometryInfo ginfo2 = new GeometryInfo(GeometryInfo.POLYGON_ARRAY);
            ginfo2.setCoordinates(vertices);
            ginfo2.setCoordinateIndices(idx2);
            ginfo2.setStripCounts(stripCount);
            ginfo2.setNormals(normals);
            ginfo2.setNormalIndices(vidx2);
    
            // Color の設定
            ginfo2.setColors(colors);
            ginfo2.setColorIndices(cidx2);
    
            // Texture の設定
            ginfo2.setTextureCoordinateParams(1,2);
            ginfo2.setTextureCoordinates(0,texture);
            ginfo2.setTextureCoordinateIndices(0,tidx2);
    
            // Material を設定して BranchGroup に追加
            Shape3D shape2 = new Shape3D(ginfo2.getGeometryArray());
            shape2.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
            shape2.setAppearance(createAppearance(1));
            trans.addChild(shape2);
        
  6. createAppearance でテクスチャを設定します。
    "Kishi32.bmp" がアルファチェネルを設定した BMP32bit 画像です。
    テクスチャ属性で DECAL を設定するとテクスチャの透明部分から立方体の色が透けて見えます。
        // Material の設定
        private Appearance createAppearance(int flag)
        {
            Appearance app = new Appearance();
            if (flag==1)
            {   BufferedImage bimage = loadAlpha("C:\\DATA\\Test\\Kishi32.bmp");
                TextureLoader texload = new TextureLoader(bimage);
                Texture2D texture2d = (Texture2D)texload.getTexture();
                app.setTexture(texture2d);
                //※ 透明度の設定
                app.setTransparencyAttributes(new TransparencyAttributes(TransparencyAttributes.BLENDED, 0.0f));
                // テクスチャ属性
                TextureAttributes txattr = new TextureAttributes();
                txattr.setTextureMode(TextureAttributes.DECAL);
                app.setTextureAttributes(txattr);
            }
            return app;
        }
        

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