二枚の画像を組み合わせてアルファチャネル付きのテクスチャを作成して Box に貼り付けます。

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

プログラムの作成

  1. モデルの中には通常の画像とアルファチャネルに設定する二枚の画像を組み合わせて張り付けるものがあります。
    今回はアルファチャネル付きのテクスチャを張り付けたモデルを生成して描画してみましょう。
    メモ帳などでタイプして TexAlphaBox.java の名前で保存して下さい。
    //★ アルファチャネル付きテクスチャを Box に張付る    前田 稔
    import java.awt.*;
    import javax.swing.*;
    import javax.media.j3d.*;
    import javax.vecmath.*;
    import com.sun.j3d.utils.universe.*;
    import com.sun.j3d.utils.geometry.*;
    import java.io.*;
    import java.net.URL;
    import com.sun.j3d.loaders.*;
    import com.sun.j3d.utils.behaviors.mouse.*;
    import java.awt.image.*;
    import javax.imageio.ImageIO;
    import com.sun.j3d.utils.image.TextureLoader;
    
    public class TexAlphaBox extends JFrame
    {
        // main Method
        public static void main(String[] args)
        {   java.awt.EventQueue.invokeLater(new Runnable()
            {   public void run()
                {   new TexAlphaBox().setVisible(true);  }
            });
        }
    
        // Constructor
        public TexAlphaBox()
        {   // JFrame の初期化
            super(" Scene test");
            setSize(340,290);
            setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            // Java3D 関係の設定
            GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
            Canvas3D canvas = new Canvas3D(config);
            add(canvas);
    
            // SimpleUniverseを生成
            SimpleUniverse universe = new SimpleUniverse(canvas);
            universe.getViewingPlatform().setNominalViewingTransform();
    
            // Scene を生成
            universe.addBranchGraph(CreateScene());
        }
    
        // Scene の生成
        public BranchGroup CreateScene()
        {   BranchGroup objRoot = new BranchGroup();
    
            // 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);
    
            // 縮小
            TransformGroup objScale = new TransformGroup();
            Transform3D t3d = new Transform3D();
            t3d.setScale(0.4);
            objScale.setTransform(t3d);
            objRoot.addChild(objScale);
    
            // Mouse 操作の設定
            TransformGroup trans = new TransformGroup();
            SetMouse(objRoot, trans);
            objScale.addChild(trans);
    
            // BOX モデルの生成
            Loader_Test f = new Loader_Test();
            Scene s = null;
            s = f.load();
    
            trans.addChild(s.getSceneGroup());
    
            // 背景色の設定
            Color3f bgColor = new Color3f(0.5f, 0.6f, 0.7f);
            Background bgNode = new Background(bgColor);
            bgNode.setApplicationBounds(bounds);
            objRoot.addChild(bgNode);
    
            return objRoot;
        }
    
        // 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);
       }
    }
    
    // ★ Loader Object Class
    class Loader_Test extends LoaderBase
    {   SceneBase   Base;
    
        public Scene load()
        {   creatscene();
            return Base;
        }
    
        @Override
        public Scene load(String fname)
        {   Base = new SceneBase();
            return Base;
        }
    	
        @Override
        public Scene load(URL aURL)
        {   Base = new SceneBase();
            return Base;
        }
    
        @Override
        public Scene load(Reader reader)
        {   Base = new SceneBase();
            return Base;
        }
    
        // Scene を生成
        public void creatscene()
        {   Base = new SceneBase();
            Base.setSceneGroup(new BranchGroup());
    
            // 立方体の座標を定義
            Point3f[] vertices =
            {  new Point3f(-1.0f, -1.0f, -1.0f), new Point3f(1.0f, -1.0f, -1.0f),
               new Point3f(-1.0f, 1.0f, -1.0f),  new Point3f(1.0f, 1.0f, -1.0f),
               new Point3f(-1.0f, -1.0f, 1.0f),  new Point3f(1.0f, -1.0f, 1.0f),
               new Point3f(-1.0f, 1.0f, 1.0f),   new Point3f(1.0f, 1.0f, 1.0f)
            };
            // 法線ベクトルを定義
            Vector3f[] normal =
            {  new Vector3f(0.0f, 0.0f, -1.0f), new Vector3f(-1.0f, 0.0f, 0.0f),
               new Vector3f(1.0f, 0.0f, 0.0f),  new Vector3f(0.0f, -1.0f, 0.0f),
               new Vector3f(0.0f, 1.0f, 0.0f),  new Vector3f(0.0f, 0.0f, 1.0f),
            };
    
            // Index を定義
            int[] indices = { 0,2,3,1, 0,4,6,2, 1,3,7,5, 0,1,5,4, 2,6,7,3, 4,5,7,6 };
            int[] normidx = { 0,0,0,0, 1,1,1,1, 2,2,2,2, 3,3,3,3, 4,4,4,4, 5,5,5,5 };
            // 矩形の区切りを定義(4角形ポリゴン*6個)
            int[] stripCount = { 4,4,4,4,4,4 };
    
            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)    // 右上,  左上
            };
            int[] texidx = { 0,1,2,3, 0,1,2,3, 0,1,2,3, 0,1,2,3, 0,1,2,3, 0,1,2,3 };
    
            // 立方体を作成
            GeometryInfo ginfo = new GeometryInfo(GeometryInfo.POLYGON_ARRAY);
            ginfo.setCoordinates(vertices);
            ginfo.setCoordinateIndices(indices);
            ginfo.setStripCounts(stripCount);
            ginfo.setNormals(normal);
            ginfo.setNormalIndices(normidx);
    
            // Texture の設定
            ginfo.setTextureCoordinateParams(1,2);
            ginfo.setTextureCoordinates(0,texture);
            ginfo.setTextureCoordinateIndices(0,texidx);
    
            // Material を設定して SceneBase に追加
            Shape3D shape = new Shape3D(ginfo.getGeometryArray());
            shape.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
            shape.setAppearance(createAppearance());
            Base.getSceneGroup().addChild(shape);
        }
    
        // Material の設定
        private Appearance createAppearance()
        {   Appearance app = new Appearance();
            Material mat = new Material();
            mat.setDiffuseColor(new Color3f(0.8f, 0.8f, 0.0f));
            app.setMaterial(mat);
    
            BufferedImage img= loadImage("C:\\DATA\\Test\\Kishi.jpg");
            BufferedImage mask= loadImage("C:\\DATA\\Test\\KishiMSK.gif");
            BufferedImage tex= null;
            tex= AlaphImg(img, mask);
    
            Texture2D texture2d = (Texture2D)new TextureLoader(tex).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;
        }
    
        // BufferedImage の入力
        public BufferedImage loadImage(String fileName)
        {   InputStream is = null;
            try
            {   is = new FileInputStream(fileName);
                BufferedImage img = ImageIO.read(is);
                return img;
            }
            catch (IOException e)
            {   throw new RuntimeException(e);  }
            finally
            {   if (is != null)
                    try { is.close(); }
                    catch (IOException e) { return null; }
            }
        }
    
        // 二枚の画像を組み合わせてアルファチャネル付き画像を作成
        public BufferedImage AlaphImg(BufferedImage img, BufferedImage mask)
        {   int pixel;
            int width = img.getWidth();
            int height = img.getHeight();
    
            BufferedImage vimg= new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
            for(int y=0; y<height; y++)
            {   for(int x=0; x<width; x++)
                {   pixel = img.getRGB(x,y) & 0Xffffff;
                    pixel |= mask.getRGB(x,y)<<24;
                    vimg.setRGB(x,y,pixel);
                }
            }
            return vimg;
        }
    }
    
  2. 二枚の画像を組み合わせてアルファチャネル付きのテクスチャを作成します。
    作成したテクスチャを立方体に貼り付けます。
    画像の周囲がグラデーションして描画され、透過部分からポリゴンの色が透けて見えます。
    マウスでモデルを操作することが出来ます。

プログラムの説明

  1. ローダーの基礎は Scene を生成する を参照して下さい。
    立方体を生成する creatscene() メソッドです。
    GeometryInfo の POLYGON_ARRAY で立方体を生成します。
    テクスチャ属性を設定するので Shape3D に ALLOW_GEOMETRY_READ を許可して下さい。
        // Scene を生成
        public void creatscene()
        {   Base = new SceneBase();
            Base.setSceneGroup(new BranchGroup());
    
            // 立方体の座標を定義
                ・・・
    
            // 立方体を作成
            GeometryInfo ginfo = new GeometryInfo(GeometryInfo.POLYGON_ARRAY);
            ginfo.setCoordinates(vertices);
            ginfo.setCoordinateIndices(indices);
            ginfo.setStripCounts(stripCount);
            ginfo.setNormals(normal);
            ginfo.setNormalIndices(normidx);
    
            // Texture の設定
            ginfo.setTextureCoordinateParams(1,2);
            ginfo.setTextureCoordinates(0,texture);
            ginfo.setTextureCoordinateIndices(0,texidx);
    
            // Material を設定して SceneBase に追加
            Shape3D shape = new Shape3D(ginfo.getGeometryArray());
            shape.setCapability(Shape3D.ALLOW_GEOMETRY_READ);
            shape.setAppearance(createAppearance());
            Base.getSceneGroup().addChild(shape);
        }
        
  2. アルファチャネル付きのテクスチャを作成して張り付ける createAppearance() メソッドです。
    "C:\\DATA\\Test\\Kishi.jpg" が騎士のテクスチャ画像です。
    "C:\\DATA\\Test\\KishiMSK.gif" がアルファチャネルに設定する白黒のグラデーション画像です。
    tex= AlaphImg(img, mask); で二枚の画像を組み合わせてアルファチャネル付きのテクスチャを作成します。
    setTransparencyAttributes() でアルファチャネルを有効にします。
    これをコメントアウトするとアルファチャネルが効かなくなるので試してみて下さい。
    テクスチャ属性で DECAL を設定するとテクスチャの透過部分からマテリアルで設定したモデルの色が透けて見えます。
        // Material の設定
        private Appearance createAppearance()
        {   Appearance app = new Appearance();
            Material mat = new Material();
            mat.setDiffuseColor(new Color3f(0.8f, 0.8f, 0.0f));
            app.setMaterial(mat);
    
            BufferedImage img= loadImage("C:\\DATA\\Test\\Kishi.jpg");
            BufferedImage mask= loadImage("C:\\DATA\\Test\\KishiMSK.gif");
            BufferedImage tex= null;
            tex= AlaphImg(img, mask);
    
            Texture2D texture2d = (Texture2D)new TextureLoader(tex).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;
        }
        
  3. 二枚の画像を組み合わせてアルファチャネル付きのテクスチャを作成する AlaphImg() メソッドです。
    詳細は アルファチャネル付き画像 を参照して下さい。
        // 二枚の画像を組み合わせてアルファチャネル付き画像を作成
        public BufferedImage AlaphImg(BufferedImage img, BufferedImage mask)
        {   int pixel;
            int width = img.getWidth();
            int height = img.getHeight();
    
            BufferedImage vimg= new BufferedImage(width, height, BufferedImage.TYPE_4BYTE_ABGR);
            for(int y=0; y<height; y++)
            {   for(int x=0; x<width; x++)
                {   pixel = img.getRGB(x,y) & 0Xffffff;
                    pixel |= mask.getRGB(x,y)<<24;
                    vimg.setRGB(x,y,pixel);
                }
            }
            return vimg;
        }
        

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