モデルの変形

ColorCube の頂点座標を操作して、変形しながら描画します。

Java Applet の実行は、次のリンクをクリックして下さい。
マウスで ColorCube を操作することが出来ます。
ColorCube の変形

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

プログラムの作成

  1. ColorCube の頂点座標を操作して「うねうね (?_?; 」と変形しながら描画します。
    //★ ColorCube を変形しながら描画する    前田 稔
    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.geometry.ColorCube;
    import com.sun.j3d.utils.behaviors.mouse.*;
    
    public class distortcube extends Applet
    {   private SimpleUniverse universe = null;
    
        // Applet 初期化
        public void init()
        {   setLayout(new BorderLayout());
            // Java3D 関係の設定
            GraphicsConfiguration config = SimpleUniverse.getPreferredConfiguration();
            Canvas3D canvas = new Canvas3D(config);
            add("Center", canvas);
    
            // SimpleUniverseを生成
            universe = new SimpleUniverse(canvas);
            universe.getViewingPlatform().setNominalViewingTransform();
    
            // Scene を生成
            universe.addBranchGraph(CreateScene());
        }
    
        // Scene の生成
        public BranchGroup CreateScene()
        {   BranchGroup objRoot = new BranchGroup();
    
            // Mouse でモデルを操作
            TransformGroup trans = new TransformGroup();
            trans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
            SetMouse(objRoot, trans);
    
            // ColorCube 生成
            ColorCube   cube = new ColorCube(0.4);
            trans.addChild(cube);
            Shape3D shape = cube.getShape();
            Appearance app = new Appearance();
            shape.setAppearance(app);
    
            // モデルを変形する Object
            distortbehavior eb = new distortbehavior(shape,1000,1000);
            eb.setSchedulingBounds(new BoundingSphere());
            trans.addChild(eb);
            objRoot.addChild(trans);
            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);
       }
    }
    
  2. モデルを変形する distortbehavior.java です。
    元は Sun Java3D の j3d\examples\distort_glyph\ に掲載されていたものです。
    ソースコードの説明はそちらを参照して下さい。
    import java.util.Enumeration;
    import javax.media.j3d.Appearance;
    import javax.media.j3d.Behavior;
    import javax.media.j3d.GeometryArray;
    import javax.media.j3d.Shape3D;
    import javax.media.j3d.Transform3D;
    import javax.media.j3d.WakeupCondition;
    import javax.media.j3d.WakeupCriterion;
    import javax.media.j3d.WakeupOnElapsedFrames;
    import javax.media.j3d.WakeupOnElapsedTime;
    import javax.vecmath.Vector3f;
    
    public class distortbehavior extends Behavior {
        // the wake up condition for the behavior
        protected WakeupCondition   m_InitialWakeupCondition    = null;
        protected WakeupCondition   m_FrameWakeupCondition      = null;
    
        // the GeometryArray for the Shape3D that we are modifying
        protected Shape3D       m_Shape3D           = null;
        protected GeometryArray m_GeometryArray         = null;
    
        protected float[]       m_CoordinateArray       = null;
        protected float[]       m_OriginalCoordinateArray   = null;
        protected Appearance    m_Appearance            = null;
    
        protected int       m_nElapsedTime          = 0;
        protected int       m_nNumFrames            = 0;
        protected int       m_nFrameNumber          = 0;
    
        private int         frame               = 0;
        protected Vector3f      m_Vector            = null;
    
        public distortbehavior(Shape3D shape3D, int nElapsedTime, int nNumFrames) {
            // allocate a temporary vector
            m_Vector = new Vector3f();
    
            m_FrameWakeupCondition = new WakeupOnElapsedFrames(0);
    
            restart(shape3D, nElapsedTime, nNumFrames);
        }
    
        public WakeupCondition restart(Shape3D shape3D, int nElapsedTime, int nNumFrames) {
            m_Shape3D = shape3D;
            m_nElapsedTime = nElapsedTime;
            m_nNumFrames = nNumFrames;
            m_nFrameNumber = 0;
    
            // create the WakeupCriterion for the behavior
            m_InitialWakeupCondition = new WakeupOnElapsedTime(m_nElapsedTime);
    
            // save the GeometryArray that we are modifying
            m_GeometryArray = (GeometryArray) m_Shape3D.getGeometry();
    
            if (m_Shape3D.isLive() == false && m_Shape3D.isCompiled() == false) {
                // set the capability bits that the behavior requires
                m_Shape3D.setCapability(Shape3D.ALLOW_APPEARANCE_READ);
                m_Shape3D.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
    
                m_Shape3D.getAppearance().setCapability(Appearance.ALLOW_POINT_ATTRIBUTES_WRITE);
                m_Shape3D.getAppearance().setCapability(Appearance.ALLOW_POLYGON_ATTRIBUTES_WRITE);
                m_Shape3D.getAppearance().setCapability(Appearance.ALLOW_TRANSPARENCY_ATTRIBUTES_WRITE);
                m_Shape3D.getAppearance().setCapability(Appearance.ALLOW_TEXTURE_WRITE);
    
                m_GeometryArray.setCapability(GeometryArray.ALLOW_COORDINATE_READ);
                m_GeometryArray.setCapability(GeometryArray.ALLOW_COORDINATE_WRITE);
                m_GeometryArray.setCapability(GeometryArray.ALLOW_COUNT_READ);
            }
    
            // make a copy of the object's original appearance
            m_Appearance = new Appearance();
            m_Appearance = (Appearance) m_Shape3D.getAppearance().cloneNodeComponent(true);
    
            // allocate an array for the model coordinates
            m_CoordinateArray = new float[3 * m_GeometryArray.getVertexCount()];
    
            // make a copy of the models original coordinates
            m_OriginalCoordinateArray = new float[3 * m_GeometryArray.getVertexCount()];
            m_GeometryArray.getCoordinates(0, m_OriginalCoordinateArray);
    
            // start (or restart) the behavior
            setEnable(true);
    
            return m_InitialWakeupCondition;
        }
    
        public void initialize() {
            // apply the initial WakeupCriterion
            wakeupOn(m_InitialWakeupCondition);
        }
    
        public void processStimulus(Enumeration criteria) {
            while (criteria.hasMoreElements()) {
                WakeupCriterion wakeUp = (WakeupCriterion) criteria.nextElement();
    
                if (wakeUp instanceof WakeupOnElapsedTime) {
                } else {
                    // we are mid explosion, modify the GeometryArray
                    m_nFrameNumber++;
                    frame++;
                    m_GeometryArray.getCoordinates(0, m_CoordinateArray);
    
                    Transform3D t3 = new Transform3D();
                    for (int n = 0; n < m_CoordinateArray.length; n += 3) {
                        m_Vector.x = m_OriginalCoordinateArray[n];
                        m_Vector.y = m_OriginalCoordinateArray[n + 1];
                        m_Vector.z = m_OriginalCoordinateArray[n + 2];
    
                        float spx = (float) (Math.sin(frame *3f / 500));
                        float spy = (float) (Math.cos(frame *5f / 500));
                        Vector3f v = new Vector3f(spx, spy, 0);
    
                        float px = (m_Vector.x - v.x);
                        float py = (m_Vector.y - v.y);
                        float pz = (m_Vector.z - v.z);
                        float d = (float) Math.sqrt(px * px + py * py + pz * pz);
    
    
                        m_Vector.add(new Vector3f(-.25f, -.25f, -.25f));
                        //m_Vector.scale(d);
    
                        t3.rotZ(d);
                        t3.rotX(d*2);
                        t3.rotY(d);
                        t3.transform(m_Vector);
    
                        m_CoordinateArray[n] = m_Vector.x;
                        m_CoordinateArray[n + 1] = m_Vector.y;
                        m_CoordinateArray[n + 2] = m_Vector.z;
    
                    }
    
                    // assign the new coordinates
                    m_GeometryArray.setCoordinates(0, m_CoordinateArray);
                }
            }
    
            if (m_nFrameNumber < m_nNumFrames) {
                // assign the next WakeUpCondition, so we are notified again
                wakeupOn(m_FrameWakeupCondition);
            } else {
                // restart
                m_nFrameNumber = 0;
                wakeupOn(m_FrameWakeupCondition);
            }
        }
    }
    

プログラムの説明

  1. 基本的なプログラムの説明は ColorCube をマウスで操作する を参照して下さい。
    ColorCube を生成して Shape3D を取得して Appearance を設定します。
    これらは ColorCube を変形するときに必要です。
    new distortbehavior(shape,1000,1000); でモデルを変形する Object を生成して TransformGroup に加えます。
    これだけで ColorCube がうねうねと変形しながら描画されます。
        // Scene の生成
        public BranchGroup CreateScene()
        {   BranchGroup objRoot = new BranchGroup();
                ・・・
    
            // ColorCube 生成
            ColorCube   cube = new ColorCube(0.4);
            trans.addChild(cube);
            Shape3D shape = cube.getShape();
            Appearance app = new Appearance();
            shape.setAppearance(app);
    
            // モデルを変形する Object
            distortbehavior eb = new distortbehavior(shape,1000,1000);
            eb.setSchedulingBounds(new BoundingSphere());
            trans.addChild(eb);
            objRoot.addChild(trans);
            return objRoot;
        }
        

Java Game Program