Graphics 版 (精华区)

发信人: seaman (翩翩少年), 信区: Graphics
标  题: JAVA3D学习系列(16)--动画的生成(中)
发信站: 哈工大紫丁香 (Tue Sep 28 19:16:52 1999), 转信

           JAVA3D学习系列(16)--动画的生成(中)


     汕头大学机电系  张杰(jzhang@mailserv.stu.edu.cn)


    上一讲我们已经介绍了一个JAVA3D的内插对象:
PositionInterpolator。本讲我们将继续介绍其它的
内插对象。

一. RotationInterpolator对象
    RotationInterpolator的构造函数有两个:
    public RotationInterpolator(Alpha alpha, 
                                TransformGroup target)
    public RotationInterpolator(Alpha alpha, 
                                TransformGroup target, 
                                Transform3D axisOfRotation, 
                                float minimumAngle, 
                                float  maximumAngle)

    RotationInterpolator的方法有:
       public void setMinimumAngle(float angle)
       public float getMinimumAngle()

       public void setMaximumAngle(float angle)
       public float getMaximumAngle()

       public void setAxisOfRotation(Transform3D axis)
       public Transform3D getAxisOfRotation()

       public void setTarget(TransformGroup target)
       public TransformGroup getTarget()

       public void processStimulus(Enumeration criteria)

    利用这个对象,我们可以在给定的时间内,使某一个局部坐标系
在按照Alpha提供的方式绕着某一个轴旋转,它的作用类似于VRML
的OrientationInterpolator节点。
    RotationInterpolator的前三个参数和我们上一讲介绍的
PositionInterpolator对象的前三个参数概念一样:
    Alpha为我们提供了旋转方式。
    target为我们提供了需要旋转的局部坐标系。
    axisOfRotation确定了旋转轴的方位。

1. 第一个构造函数的运行结果
    假如我们利用的是第一个构造函数,我们所获得的最大角度为
2*PI,最小角度为0,坐标系绕着Y轴,按照Alpha给出的旋转方式
旋转。

2. 第二个构造函数的运行结果
    我们来看一下OrientationInterpolator第二个构造函数的后两
个参数,它们给出了旋转的最大最小的角度。
    下面的程序Rot.java利用了RotationInterpolator对象,使一个
立方体绕着自己的Y轴不停地旋转:先正转180度。停顿几秒后,又反
转180度,再停顿几秒钟。

//Rot.java
import com.sun.j3d.utils.geometry.ColorCube;
import java.applet.Applet;
import java.awt.BorderLayout;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;

public class Rot extends Applet {
    private BranchGroup createSceneGraph( ) {
        float min = 0.0f;
        float max = (float) Math.PI;
        BranchGroup objRoot = new BranchGroup();
        BoundingSphere bound=new BoundingSphere(
           new Point3d(0.0,0.0,0.0),50.);

        Transform3D tr=new Transform3D();
        TransformGroup group=new TransformGroup(tr);
        group.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        group.addChild(new ColorCube());

        Alpha xtranAlpha = new Alpha(-1,
            Alpha.DECREASING_ENABLE|Alpha.INCREASING_ENABLE,
            0, 0,5000, (long)0.5, 5000, 5000,(long)0.5, 5000);
        RotationInterpolator tran =
            new RotationInterpolator(xtranAlpha, group, tr,           
                                     min,max);
        tran.setSchedulingBounds(bound);
        group.addChild(tran);

        Color3f bgColor = new Color3f(1.0f, 1.0f, 1.0f);
        Background bg = new Background(bgColor);
        bg.setApplicationBounds(bound);
        objRoot.addChild(bg);

        objRoot.addChild(group);
        return objRoot;
    }

    public Rot() {
        setLayout(new BorderLayout());
        Canvas3D c = new Canvas3D(null);
        add("Center", c);
          ViewPlatform        viewPlatform;
          Viewer viewer = new Viewer(c);
          Vector3d viewpoint = new Vector3d(0.0, 0.0, 10.0);   
                                                 //初始观察点位置
       Transform3D t = new Transform3D();
       t.set(viewpoint);
          ViewingPlatform v = new ViewingPlatform( );
          v.getViewPlatformTransform().setTransform(t);

        BranchGroup scene = createSceneGraph();
       SimpleUniverse u =   new SimpleUniverse( v,   viewer);
           
       u.getViewingPlatform();
       u.addBranchGraph(scene);
    }

    public static void main(String[] args) {
        new MainFrame(new Rot(), 400,400);
    }
}
//end of Rot.java

    我们给出相应的VRML语言编写出的程序,由VRML程序的
运行结果可以看出,VRML程序无法使形体的速度渐变,而只
能突变,因而JAVA3D在这一方面功能较强。

#VRML V2.0 utf8
DEF T Transform{
  children Shape{
    appearance Appearance{material Material{diffuseColor 1 0 .5}}
    geometry Box{}}
}
DEF TS TimeSensor{
   loop TRUE
   cycleInterval 20}

DEF OI OrientationInterpolator{
  key [ 0 .25 .5 .75 1]
  keyValue[0 1 0 0 ,0 1 0 3.14,0 1 0 3.14, 0 1 0 0, 0 1 0 0]
  }

ROUTE TS.fraction TO OI.fraction
ROUTE OI.value TO T.rotation
#end of Rot.wrl

    如果我们在JAVA3D程序的
        Transform3D tr=new Transform3D();
    后面加上一句:
        tr.rotZ(Math.PI/2) ;
    则形体从绕着Y轴旋转改为绕着X轴旋转。


二. ColorInterpolator对象
    ColorInterpolator的构造函数也有两个:
    public ColorInterpolator(Alpha alpha, Material target)
    public ColorInterpolator(Alpha alpha, Material target, 
                             Color3f startColor, 
                             color3f endColor)

    ColorInterpolator的方法有:
       public void setStartColor(Color3f color)
       public void getStartColor(Color3f color)

       public void setEndColor(Color3f color)
       public void getEndColor(Color3f color)

       public void setTarget(Material target)
       public Material getTarget()

       public void processStimulus(Enumeration criteria)

    利用这个对象,我们可以在给定的时间内,使某一个Material
对象的漫反射光DiffuseColor发生变化。按照Alpha提供的方式变化,
它的作用类似于VRML的ColorInterpolator节点,两者的名字完全一样。

1. 第一个构造函数的运行结果
    如果我们采用的是第一个构造函数,则startColor为黑色,
endColor为白色。本人利用此方法编写了几个程序,发现形体的
颜色难以控制,因而建议大家少使用这个方法。

2. 第二个构造函数的运行结果
    采用第二个构造函数时,我们需要设定startColor和endColor
这两个颜色。不过要注意,为了使Material对象的DiffuseColor
产生变化的效果,我们应在空间增加一个对着形体照射的光线,
否则形体显示的依旧是辐射光EmissiveColor。
    但我们经过多次实验,发现ColorInterpolator对象产生的
效果不是我们所预期的效果,例如,如果我们想使形体的
diffuseColor从颜色a变到颜色b,显示的结果却是形体的
emissiveColor到diffuseColor的变化。程序如下:
//Color.java

import java.applet.Applet;
import java.awt.BorderLayout;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.image.TextureLoader;
import com.sun.j3d.utils.universe.*;
import com.sun.j3d.utils.geometry.*;
import javax.media.j3d.*;
import javax.vecmath.*;

public class Color extends Applet {

    private BranchGroup createSceneGraph() {
      BranchGroup objRoot = new BranchGroup();
           objRoot.addChild(createObject());
           Color3f bgColor = new Color3f(1.0f, 1.0f, 1.0f);
      BoundingSphere bounds=new BoundingSphere(new Point3d(0.0,0.0,0.0),100.0);
        Background bg = new Background(bgColor);
        bg.setApplicationBounds(bounds);
        objRoot.addChild(bg);

    Color3f light1Color = new Color3f(1.0f, 1.0f, 1.0f);
      Vector3f light1Direction  = new Vector3f(4.0f, -7.0f, -12.0f);
 
      DirectionalLight light1
            = new DirectionalLight(light1Color, light1Direction);
      light1.setInfluencingBounds(bounds);

      objRoot.addChild(light1);

        objRoot.compile();
        return objRoot;
    }

    private Group createObject() {
        Transform3D t = new Transform3D();
        TransformGroup objTrans = new TransformGroup(t);
        objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);

       Appearance ap=new Appearance();
        ap.setCapability(Appearance.ALLOW_MATERIAL_WRITE);
        ap.setCapability(Appearance.ALLOW_COLORING_ATTRIBUTES_WRITE);
         Material mat = new Material( );
        mat.setCapability(Material.ALLOW_COMPONENT_WRITE);
       Color3f emissive = new Color3f(0.0f, 1.0f, 0.0f);
         Color3f diffuse   = new Color3f(0.0f, 0.0f, 1.0f);
      mat.setEmissiveColor(emissive);
          mat.setDiffuseColor(diffuse);            
         ap.setMaterial(mat);          

      PolygonAttributes pa = new PolygonAttributes();
          pa.setCullFace(PolygonAttributes.CULL_NONE);
      ap.setPolygonAttributes(pa);

      ColoringAttributes ca = new ColoringAttributes( );
        ca.setCapability(ColoringAttributes.ALLOW_COLOR_WRITE);
      ap.setColoringAttributes( ca);
              
      Alpha alpha = new Alpha(-1,
             Alpha.INCREASING_ENABLE|Alpha.DECREASING_ENABLE,
             0, 0, 8000, 0, 0, 8000, 0, 0);
      ColorInterpolator  ci = new ColorInterpolator(alpha, mat,
                      new Color3f(1.0f,0.0f, 1.0f), new Color3f(0.0f, 0.0f, 1.0f));
    
      BoundingSphere bounds=new BoundingSphere(new Point3d(0.0,0.0,0.0),100.0);
      ci.setSchedulingBounds(bounds);

     Shape3D shape = new myShape();
        shape.setCapability(Shape3D.ALLOW_APPEARANCE_WRITE);
        shape.setAppearance(ap);
        objTrans.addChild(shape);
  
    Transform3D yAxis = new Transform3D();
        Alpha rotationAlpha = new Alpha(-1, Alpha.INCREASING_ENABLE,
                       0, 0, 4000, 0, 0, 0, 0, 0);

        RotationInterpolator rotator =
            new RotationInterpolator(rotationAlpha, objTrans, yAxis,
                                     0.0f, (float) Math.PI*2.0f);
        rotator.setSchedulingBounds(bounds);
        objTrans.addChild(rotator);
        
        return objTrans;
    }

    public Color() {
        setLayout(new BorderLayout());
        Canvas3D c = new Canvas3D(null);
        add("Center", c);

        BranchGroup scene = createSceneGraph();
        SimpleUniverse u = new SimpleUniverse(c);
        u.getViewingPlatform().setNominalViewingTransform();

        u.addBranchGraph(scene);
    }

    public static void main(String[] args) {
        new MainFrame(new Color(), 540,361);
    }
}

//end of Color.java
----------------------
//myShape.java
import javax.media.j3d.*;
import javax.vecmath.*;

public class myShape extends Shape3D {
    private float vert[] = {
       -.3f,-.3f,0.0f,
       -.3f,.3f,0.0f,
       -.1f,-.3f,0.0f,
       -.1f,.3f,0.0f,
       .1f,-.3f,0.0f,
       .1f,.3f,0.0f,
       .3f,-.3f,0.0f,
       .3f,.3f,0.0f,
       .4f,.4f,0.0f,       };
           
    public myShape() {
        int i, face;
        TriangleArray shape = new TriangleArray(9, 
           TriangleArray.COORDINATES|TriangleArray.NORMALS);
        shape.setCoordinates(0,vert);

        Vector3f normal = new Vector3f();
        Vector3f v1 = new Vector3f();
        Vector3f v2 = new Vector3f();
        Point3f [] pts = new Point3f[3];
        for (i=0;i<3;i++) pts[i] = new Point3f();
        
      for(face =0; face<3; face++) {
        shape.getCoordinates(face*3,pts);
        v1.sub(pts[1],pts[0]);
        v2.sub(pts[2],pts[0]);
        normal.cross(v1,v2);
        normal.normalize();
        for (i=0;i<3;i++) {
           shape.setNormal((face*3+i), normal);
           }
       }
      this.setGeometry(shape);

    }

}
      
//end of myShape.java

    我们给出程序对应的VRML程序color.wrl
#VRML V2.0 utf8
DEF T Transform{
      children Shape{
        appearance Appearance{
           material DEF M Material{diffuseColor 0 1 0}}
        geometry IndexedFaceSet{
          coord Coordinate{point [-0.3 -0.3 0,-0.3 0.3 0,
                                  -0.1 -0.3 0,-0.1 0.3 0,
                                   0.1 -0.3 0, 0.1 0.3 0,
                                   0.3 -0.3 0, 0.3 0.3 0,
                                   0.4  0.4 0]}
          coordIndex[0 3 1 -1, 2 5 4 -1, 6 8 7]
          solid FALSE
           }
}
}

DEF TS TimeSensor{
   loop TRUE
   cycleInterval 8}

DEF CI ColorInterpolator{
     key[0 .5 1]
     keyValue[ 0 1 0, 0 0 1 , 0 1 0]
}

DEF OI OrientationInterpolator{
     key[0    .5   1]
     keyValue[ 0 1 0 0 , 0 1 0 3.14,  0 1 0 6.28]
}

Viewpoint {
   position 0 .3 1
   orientation 1 0 0 -.3}

Background{skyColor 1 1 1}

ROUTE TS.fraction TO CI.fraction
ROUTE TS.fraction TO OI.fraction
ROUTE CI.value TO M.diffuseColor
ROUTE OI.value TO T.rotation

#end of color.wrl


三. ScaleInterpolator对象
    ScaleInterpolator对象的构造函数有两个:
    public ScaleInterpolator(Alpha alpha, 
                             TransformGroup target)
    public ScaleInterpolator(Alpha alpha, 
                             TransformGroup target, 
                             Transform3D axisOfScale, 
                             float minimumScale, 
                             float  maximumScale)

    ScaleInterpolator的方法有:
       public void setMinimumScale(float scale)
       public float getMinimumScale()

       public void setMaximumScale(float scale)
       public float getMaximumScale()

       public void setAxisOfScale(Transform3D axis)
       public Transform3D getAxisOfScale()

       public void setTarget(TransformGroup target)
       public TransformGroup getTarget()

       public void processStimulus(Enumeration criteria)

       public void updateNodeReferences(NodeReferenceTable 
            referenceTable)

    利用这个对象,我们可以在给定的时间内,使某一个局部坐标系
的各个方向按照Alpha提供的方式进行比例变化,它的作用在VRML
程序中可以用PositionInterpolator来代替。
    ScaleInterpolator的第一个构造函数为我们提供了缺省的比例数
值,最大为1.0f,最小为0.1f。下面的程序利用第一个构造函数使一
个立方体在一定的时间内按照Alpha给出的变化方式在各个方向上产生
了相同的比例变化,为了比较,我们还给出了相应的VRML语言编写的程序。
//Scale1.java
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.event.*;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;

public class Scale1 extends Applet {
    public BranchGroup createSceneGraph() {
        BranchGroup objRoot = new BranchGroup();

        Transform3D tran3d=new Transform3D();
        tran3d.rotX(0.4);
        TransformGroup objTrans = new TransformGroup(tran3d);
        objRoot.addChild(objTrans);

        Transform3D t =new Transform3D();
        t.rotX(0.4);
        TransformGroup obj = new TransformGroup(t);
        objTrans.addChild(obj);
        obj.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        obj.addChild(new ColorCube(0.4));

        Alpha scaleAlpha = new Alpha(-1,
                        Alpha.INCREASING_ENABLE|Alpha.DECREASING_ENABLE,
                                        0, 0, 4000, 0, 0, 4000, 0, 0);
        ScaleInterpolator scale =
           new ScaleInterpolator(scaleAlpha, obj);
        BoundingSphere bounds =
            new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
        scale.setSchedulingBounds(bounds);
       
        obj.addChild(scale);
        objRoot.compile();

        return objRoot;
        }

    public Scale1() {
        setLayout(new BorderLayout());
        Canvas3D c = new Canvas3D(null);
        add("Center", c);
        BranchGroup scene = createSceneGraph();
        SimpleUniverse u = new SimpleUniverse(c);
        u.getViewingPlatform().setNominalViewingTransform();
        u.addBranchGraph(scene);
    }
        public static void main(String[] args) {
                new MainFrame(new Scale1(),400,400);      
    }
}
        
//end of Scale1.java
----------------------Scale1.wrl----------
#VRML V2.0 utf8
DEF T Transform{
  children Shape{
    appearance Appearance{material Material{diffuseColor 1 0 .5}}
    geometry Box{}}
}
DEF TS TimeSensor{
   loop TRUE
   cycleInterval 8}

EF PI PositionInterpolator{
  key [ 0 .5 1]
  keyValue[1 1 1, 0.1 0.1 0.1 1 1 1]
  }

ROUTE TS.fraction TO PI.fraction
ROUTE PI.value TO T.scale
#end of Scale1.wrl

    ScaleInterpolator的第二个构造函数允许我们设置最大及最小
的比例数值。我们利用它编写了下面的这个程序,利用它,可以设
置我们所需要的比例数值。
//Scale2.java
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.event.*;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;

public class Scale2 extends Applet {
    public BranchGroup createSceneGraph() {
        BranchGroup objRoot = new BranchGroup();

        Transform3D tran3d=new Transform3D();
        tran3d.rotX(0.4);
        TransformGroup objTrans = new TransformGroup(tran3d);
        objRoot.addChild(objTrans);

        Transform3D t =new Transform3D();
        t.rotX(0.4);
        TransformGroup obj = new TransformGroup(t);
        objTrans.addChild(obj);
        obj.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        obj.addChild(new ColorCube(0.4));

        Alpha scaleAlpha = new Alpha(-1,
                        Alpha.INCREASING_ENABLE|Alpha.DECREASING_ENABLE,
                                        0, 0, 4000, 0, 0, 4000, 0, 0);
        ScaleInterpolator scale =
           new ScaleInterpolator(scaleAlpha, obj,t,1.0f,0.4f);
        BoundingSphere bounds =
            new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
        scale.setSchedulingBounds(bounds);
       
        obj.addChild(scale);
        objRoot.compile();

        return objRoot;
        }

    public Scale2() {
        setLayout(new BorderLayout());
        Canvas3D c = new Canvas3D(null);
        add("Center", c);
        BranchGroup scene = createSceneGraph();
        SimpleUniverse u = new SimpleUniverse(c);
        u.getViewingPlatform().setNominalViewingTransform();
        u.addBranchGraph(scene);
    }
        public static void main(String[] args) {
                new MainFrame(new Scale2(),400,400);      
    }
}

//end of Scale2.java


四. SwitchValueInterpolator
    SwitchValueInterpolator对象的构造函数有两个:
    public SwitchValueInterpolator(Alpha alpha, 
                                   Switch target)
    public SwitchValueInterpolator(Alpha alpha, 
                                   Switch target, 
                                   int  firstChildIndex, 
                                   int lastChildIndex)

    SwitchValueInterpolator的方法有:
       public void setFirstChildIndex(int firstIndex)
       public int getFirstChildIndex()

       public void setLastChildIndex(int lastIndex)
       public int getLastChildIndex()

       public void setTarget(Switch target)
       public Switch getTarget()

       public void processStimulus(Enumeration criteria)

    利用这个对象,我们可以在屏幕上在不同的时间分别显示
不同的形体。例如下面程序里,计算机按循环显示形体,每一个
周期显示的内容为:大立方体--球--圆锥--小立方体--圆锥--球。
当然,当我们采用第一个构造函数时,结果和本程序一样。
当我们将程序中的:
SwitchValueInterpolator sv =
           new SwitchValueInterpolator(scaleAlpha, s,0,4);
改为:
SwitchValueInterpolator sv =
           new SwitchValueInterpolator(scaleAlpha, s,0,3);
时,每一个周期显示的内容为:大立方体--球--圆锥--球,由此看
来,第四个形体没有显示出来。
//mySwitch.java
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.event.*;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;

public class mySwitch extends Applet {
    public BranchGroup createSceneGraph() {
        BranchGroup objRoot = new BranchGroup();

        Transform3D tran3d=new Transform3D();
        tran3d.rotX(0.4);
        TransformGroup objTrans = new TransformGroup(tran3d);
        objRoot.addChild(objTrans);

        Transform3D t =new Transform3D();
        t.rotX(0.4);
              TransformGroup obj = new TransformGroup(t);
        Switch s = new Switch( );
              s.addChild(new ColorCube(0.4));
              s.addChild(new Sphere( ));
              s.addChild(new Cone( ));
              s.addChild(new ColorCube(0.2));
              s.setCapability(Switch.ALLOW_SWITCH_WRITE);
        objTrans.addChild(obj);
        obj.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
        
             obj.addChild(s);
        Alpha scaleAlpha = new Alpha(-1,
                        Alpha.INCREASING_ENABLE|Alpha.DECREASING_ENABLE,
                                        0, 0, 4000, 0, 4000, 4000, 0, 4000);
        SwitchValueInterpolator sv =
           new SwitchValueInterpolator(scaleAlpha, s,0,4);
        BoundingSphere bounds =
            new BoundingSphere(new Point3d(0.0,0.0,0.0), 100.0);
        sv.setSchedulingBounds(bounds);
       
        obj.addChild(sv);

    Color3f light1Color = new Color3f(1.0f, 1.0f, 0.9f);
      Vector3f light1Direction  = new Vector3f(4.0f, -7.0f, -12.0f);

      DirectionalLight light1
            = new DirectionalLight(light1Color, light1Direction);
      light1.setInfluencingBounds(bounds);

      objRoot.addChild(light1);

        objRoot.compile();

        return objRoot;
        }

    public mySwitch() {
        setLayout(new BorderLayout());
        Canvas3D c = new Canvas3D(null);
        add("Center", c);
        BranchGroup scene = createSceneGraph();
        SimpleUniverse u = new SimpleUniverse(c);
        u.getViewingPlatform().setNominalViewingTransform();
        u.addBranchGraph(scene);
    }
        public static void main(String[] args) {
                new MainFrame(new mySwitch(),400,400);      
    }
}

//end of mySwitch.java

--
※ 来源:·BBS 水木清华站 bbs.net.tsinghua.edu.cn·[FROM: 202.192.158.102]

--
☆ 来源:.哈工大紫丁香 bbs.hit.edu.cn.[FROM: sunsoft.bbs@bbs.net.]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:207.321毫秒