プログラムで作成したチューブにテクスチャを貼り付けて描画します。

Applet でプログラムを体験できます。
チューブにテクスチャを貼付る

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

プログラムの作成

  1. メモ帳などでタイプして TexTube.java の名前で保存して下さい。
    //★ プログラムで Tube を作成して Texture を貼り付ける    前田 稔
    import java.awt.*;
    import javax.swing.*;
    import java.io.*;
    import java.awt.image.BufferedImage;
    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.image.TextureLoader;
    
    public class TexTube extends JFrame
    {
        int     KAKU = 6;       // チューブの角数
        int     VNUM = KAKU+1;  // 頂点座標の数
    
        // main Method
        public static void main(String[] args)
        {   new TexTube();  }
    
        // Constructor
        public TexTube()
        {   // JFrame の初期化
            super("Tube 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());
    
            // JFrame の表示
            setVisible(true);
        }
    
        // テクスチャを張り付けたチューブを生成
        private BranchGroup CreateScene()
        {   int i;
            BranchGroup objRoot = new BranchGroup();
    
            Point3d[] vect = new Point3d[VNUM*2];       // チューブの頂点座標
            TexCoord2f[] tex = new TexCoord2f[VNUM*2];  // チューブのテクスチャ座標
    
            for(i=0; i<VNUM*2; i++) vect[i] = new Point3d();
            float   dt = 1.0f/KAKU;
            for(i=0; i<VNUM; i++)
            {   // 頂点座標の計算
                RotY(360.0f/KAKU*i, 0.5f, vect[i*2+1]);
                vect[i*2].x = vect[i*2+1].x;
                vect[i*2].z = vect[i*2+1].z;
                vect[i*2].y = 0.5f;
                // テクスチャ座標の計算
                tex[i*2+1] = new TexCoord2f(i*dt,0.0f);
                tex[i*2] = new TexCoord2f(i*dt,1.0f);
            }
            int[]   stripCounts = { VNUM*2 };
    
            // 背景色を設定
            Background bg = new Background(new Color3f(0.5f, 0.5f, 0.5f));
            bg.setApplicationBounds(new BoundingSphere(new Point3d(), 100.0));
            objRoot.addChild(bg);
    
            // Mouse 操作の設定
            TransformGroup trans = new TransformGroup();
            SetMouse(objRoot, trans);
    
            // チューブを作成
            TriangleStripArray geometry = new TriangleStripArray(vect.length,
                GeometryArray.COORDINATES | GeometryArray.TEXTURE_COORDINATE_2, stripCounts);
            geometry.setCoordinates(0, vect);
            geometry.setTextureCoordinates(0, 0, tex);
    
            // Appearance の設定
            Shape3D shape = new Shape3D(geometry, createAppearance());
    
            // BranchGroup に登録
            trans.addChild(shape);
            objRoot.addChild(trans);
            return objRoot;
        }
    
        // Y軸で回転計算(rt=度)、中心(0,0)、半径(len)
        public void RotY(float rt, float len, Point3d vect)
        {   vect.x = (float)(Math.sin(rt / 180 * Math.PI)) * len;
            vect.z = (float)(Math.cos(rt / 180 * Math.PI)) * len;
            vect.y = -0.5;
        }
    
        // 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);
        }
    
        // Appearance の設定
        private Appearance createAppearance()
        {   // ポリゴンにテクスチャを設定
            BufferedImage bimage = loadImage("C:\\DATA\\Test\\ayu.gif");
            //BufferedImage bimage = loadImage("C:\\DATA\\Test\\star.gif");
            Texture2D texture2d = (Texture2D)new TextureLoader(bimage, this).getTexture();
    
            // カリングしない
            PolygonAttributes pattr = new PolygonAttributes();
            pattr.setPolygonMode(PolygonAttributes.POLYGON_FILL);
            pattr.setCullFace(PolygonAttributes.CULL_NONE); //両面を描画
            //pattr.setCullFace(PolygonAttributes.CULL_BACK); //裏面をカリング
    
            Appearance ap = new Appearance();
            ap.setTexture(texture2d);
            ap.setPolygonAttributes(pattr);
            return ap;
        }
    
        // BufferedImage の入力
        public static 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) {}
            }
        }
    }
    
  2. ソースプログラムをコンパイルして class オブジェクトを実行して下さい。
    張り付けられたチューブが描画されたら完成です。

プログラムの説明

  1. チューブモデルの作成方法は チューブを描画 を参照して下さい。
    大域領域で KAKU と VNUM を定義します。
    KAKU の初期値は6なので、6角形のチューブが作成されます。
    円筒にするには、16以上の値を設定して下さい。
        public class TubeNormal extends JFrame
        {
            int     KAKU = 6;       // チューブの角数
            int     VNUM = KAKU+1;  // 頂点座標の数
        
  2. CreateScene() メソッドです。
    TriangleStripArray を使って三角形ポリゴンを組み合わせて作成します。
    Point3d[] vect がチューブの頂点座標の領域です。
    TexCoord2f[] tex がチューブのテクスチャ座標の領域です。
    以前は Point2f[] 配列を使っていたのですが、奨励されていないようです。
    チューブの座標は、回転座標を求める専用のメソッド RotY() を使って計算します。
    Y座標がチューブの高さで -0.5 と 0.5 に設定します。
    Y軸を基点に、X座標とZ座標に回転座標を求めます。
    テクスチャ座標は 1.0 をチューブの角数で割って求めます。
    stripCounts は TriangleStripArray の頂点の個数です。
        // テクスチャを張り付けたチューブを生成
        private BranchGroup CreateScene()
        {   int i;
            BranchGroup objRoot = new BranchGroup();
    
            Point3d[] vect = new Point3d[VNUM*2];       // チューブの頂点座標
            TexCoord2f[] tex = new TexCoord2f[VNUM*2];  // チューブのテクスチャ座標
    
            for(i=0; i<VNUM*2; i++) vect[i] = new Point3d();
            float   dt = 1.0f/KAKU;
            for(i=0; i<VNUM; i++)
            {   // 頂点座標の計算
                RotY(360.0f/KAKU*i, 0.5f, vect[i*2+1]);
                vect[i*2].x = vect[i*2+1].x;
                vect[i*2].z = vect[i*2+1].z;
                vect[i*2].y = 0.5f;
                // テクスチャ座標の計算
                tex[i*2+1] = new TexCoord2f(i*dt,0.0f);
                tex[i*2] = new TexCoord2f(i*dt,1.0f);
            }
            int[]   stripCounts = { VNUM*2 };
        
  3. 背景色の設定と Mouse 操作は「チューブを描画」と同じ要領です。
    TriangleStripArray でチューブを作成します。
    テクスチャを張り付けるので、フラグに TEXTURE_COORDINATE_2 を追加して下さい。
    setTextureCoordinates(0, 0, tex); でテクスチャ座標を設定します。
            // チューブを作成
            TriangleStripArray geometry = new TriangleStripArray(vect.length,
                GeometryArray.COORDINATES | GeometryArray.TEXTURE_COORDINATE_2, stripCounts);
            geometry.setCoordinates(0, vect);
            geometry.setTextureCoordinates(0, 0, tex);
    
            // Appearance の設定
            Shape3D shape = new Shape3D(geometry, createAppearance());
    
            // BranchGroup に登録
            trans.addChild(shape);
            objRoot.addChild(trans);
            return objRoot;
        }
        
  4. createAppearance() メソッドでマテリアルとカリングの設定を行います。
    "C:\\DATA\\Test\\ayu.gif" がテクスチャ画像です。
    サイズに合わせて伸縮されるので、適当な画像を用意して下さい。
    カリングすると外側しか描画されないので「両面描画」に設定しています。
        // Appearance の設定
        private Appearance createAppearance()
        {   // ポリゴンにテクスチャを設定
            BufferedImage bimage = loadImage("C:\\DATA\\Test\\ayu.gif");
            Texture2D texture2d = (Texture2D)new TextureLoader(bimage, this).getTexture();
    
            // カリングしない
            PolygonAttributes pattr = new PolygonAttributes();
            pattr.setPolygonMode(PolygonAttributes.POLYGON_FILL);
            pattr.setCullFace(PolygonAttributes.CULL_NONE); //両面を描画
            //pattr.setCullFace(PolygonAttributes.CULL_BACK); //裏面をカリング
    
            Appearance ap = new Appearance();
            ap.setTexture(texture2d);
            ap.setPolygonAttributes(pattr);
            return ap;
        }
        
  5. テクスチャ画像の入力や、回転座標の計算や、Mouse を操作するメソッドなどは従来と同じです。
    KAKU にもっと大きな値を設定して試して下さい。
    裏面をカリングして描画してみて下さい。
    法線ベクトルを設定して描画してみて下さい。

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