Java 版 (精华区)

发信人: bali (阿奔), 信区: Java
标  题: JAVA3D学习系列(15)--动画的生成(上) 
发信站: 紫 丁 香 (Fri Mar 24 11:05:34 2000), 转信

发信人: vrml (3d), 信区: Java
标  题: JAVA3D学习系列(15)--动画的生成(上)
发信站: BBS 水木清华站 (Mon Apr 26 11:47:21 1999)
          JAVA3D学习系列(15)--动画的生成(上)
     汕头大学机电系  张杰(jzhang@mailserv.stu.edu.cn)
    1997年底正式成为国际标准的VRML2.0是我们编写简单
三维应用程序的一个非常合适的计算机语言,利用它,我们可以
非常方便地编写三维动画、交互式的三维游戏,当然,只能
是一些较为简单的三维动画及交互式三维游戏。而利用JAVA3D
则可以编写出较为复杂的三维动画及交互式三维游戏。
    前面我们介绍了JAVA3D的形体生成等方面的知识,JAVA3D
三维应用程序最吸引人之处是它可以用来制作三维动画、三维
游戏等。为了掌握JAVA3D三维动画、三维游戏的编程,我们首先
要掌握三维形体在空间的运动控制。
    VRML语言有6个内插器节点和7个传感器节点,同样地,在
JAVA3D中,也有和VRML内插器节点类似的Interpolator对象,它
们和另一个Alpha类结合在一起,可以编写出各种类型的三维动画
程序。
    下面我们就介绍这些对象及其应用方法。
一. Alpha对象
     Alpha类的常数有:
       public static final int INCREASING_ENABLE
       public static final int DECREASING_ENABLE
     它的构造函数有:
       public Alpha()
此时,它的缺省值为:
       loopCount                     -1
       mode                          INCREASING_ENABLE
       triggerTime                   0
       phaseDelayDuration            0
       increasingAlphaDuration       1000
       increasingAlphaRampDuration   0
       alphaAtOneDuration            0
       decreasingAlphaDuration       0
       decreasingAlphaRampDuration   0
       alphaAtZeroDuration           0
     Alpha的其它构造函数有:
       public Alpha(int loopCount,
                    long increasingAlphaDuration)
       public Alpha(int loopCount,
                    long triggerTime,
                    long  phaseDelayDuration,
                    long increasingAlphaDuration,
                    long  increasingAlphaRampDuration,
                    long  alphaAtOneDuration)
       public Alpha(int loopCount,
                    int mode,
                    long triggerTime,
                    long  phaseDelayDuration,
                    long increasingAlphaDuration,
                    long  increasingAlphaRampDuration,
                    long  alphaAtOneDuration,
                    long  decreasingAlphaDuration,
                    long  decreasingAlphaRampDuration,
                    long  alphaAtZeroDuration)
    Alpha的方法有:
      public float value()
      public float value(long atTime)
      public void setStartTime(long startTime)
      public long getStartTime()
      public void setLoopCount(int loopCount)
      public int getLoopCount()
      public void setMode(int mode)
      public int getMode()
      public void setTriggerTime(long triggerTime)
      public long getTriggerTime()
      public void setPhaseDelayDuration(long phaseDelayDuration)
      public long getPhaseDelayDuration()
      public void setIncreasingAlphaDuration(long
            increasingAlphaDuration)
      public long getIncreasingAlphaDuration()
      public void setIncreasingAlphaRampDuration(long
            increasingAlphaRampDuration)
      public long getIncreasingAlphaRampDuration()
      public void setAlphaAtOneDuration(long alphaAtOneDuration)
      public long getAlphaAtOneDuration()
      public void setDecreasingAlphaDuration(long
            decreasingAlphaDuration)
      public long getDecreasingAlphaDuration()
      public void setDecreasingAlphaRampDuration(long
            decreasingAlphaRampDuration)
      public long getDecreasingAlphaRampDuration()
      public void setAlphaAtZeroDuration(long alphaAtZeroDuration)
      public long getAlphaAtZeroDuration()
      public boolean finished()
    从VRML的各个内插器节点的定义来看,我们可以看到,每一个
内插器节点都有一个key字段和一个keyValue字段。key字段定义
一个数组,数值从0到1。
    所有的内插器节点在使用时都需要与TimeSensor(时间传感器)
配合使用。TimeSensor把给定的时间周期归一化,虽然时间的周期
cycleInterval 有给定的秒数,但计算机内部将其处理成从0.0到
1.0,即起始时间为0.0,终止时间为1.0,假如一个时间周期为
20(单位均为秒),则第6秒的归一化结果是0.3,第10秒的归一化
结果是0.5,第20秒的归一化结果是1.0。
    JAVA3D里的Alpha类和VRML的key字段的功能类似,它也是用于
输出归一化的时间,不过它能够处理更加复杂的时间安排问题。
    Alpha可以输出从0到1之间的数值给特定的内插对象,当Alpha
输出的数值为0时,对应的特定内插对象的值为最小;当Alpha输出
的数值为1时,对应的特定内插对象的值为最大;当Alpha输出的数
值为0到1之间的数值时,对应的特定内插对象生成和Alpha成相同
比例的数值。假设某一时刻Alpha输出的数值为0.2,则对应的特定
内插对象的当前值为最小值加上最大最小值之差乘以0.2。
           (当前值-最小值)/(最大值-最小值)=0.2
    JAVA3D里的各种Interpolator对象和VRML的内插节点的作用
比较类似,可用来旋转形体、移动形体的坐标、变化形体的颜色等。
    假设我们要让一个形体在规定的时间内按照指定的方式运动,
我们首先要给出时间段的大小,还要指出时间是否要循环。这些内容
都是由Alpha类来完成的。
    我们在前面已多次用到Alpha类,基本上我们用它及一个旋转内
插器RotationInterpolator来使形体绕着其所在的局部坐标系不停
地旋转。下面是我们眼熟的语句,语句的作用是让形体以4秒为一周
期,不停地绕着某一个轴旋转(Y轴):
      Alpha rotationAlpha = new Alpha(-1,
                                      Alpha.INCREASING_ENABLE,
                                      0, 0,
                                      4000, 0, 0,
                                      0, 0, 0);
      RotationInterpolator rotator =
            new RotationInterpolator(rotationAlpha, obj, temp,
                                  0.0f, (float) Math.PI*2.0f);
    从中我们可以看到,Alpha构造函数中:
    loopCount表示循环的次数,例如如果我们将前面介绍的Ex4_03.java
的loopCount设为10,则小丑会旋转10周,然后停止。不过在一些运行速度
慢的计算机上会出现少几次的情况,如作者本人使用的一台机器是
Pentium 586/100的计算机,当loopCount为10时,只看到小丑旋转了7次,
因为程序从开始运行到出现画面,需要一段时间。loopCount为-1时表示
无限循环。我们可以利用下面两个方法设置或获得loopCount:
        public void setLoopCount(int loopCount)
        public int getLoopCount()
    mode表示Alpha每一周期的运行方式,一共有三种:INCREASING_ENABLE、
DECREASING_ENABLE、INCREASING_ENABLE|DECREASING_ENABLE。第一种
方式表示Alpha的数值从0到1,相对应的内插对象的数值从最小到
最大;第二种方式表示Alpah的数值从1到0,相对应的内插对象的数值
从最大到最小;第三种方式表示Alpah的数值从0到1,然后从1到0,
相对应的内插对象的数值从最小到最大,然后又从最大到最小。
我们前面用到的Alpha,它每一个周期的数值,都是从0到1,对应的内插
对象的数值,在每一个循环周期里,都是从最小到最大。我们可以
利用下面两个方法,设置或获得mode:
        public void setMode(int Mode)
        public int getMode()
    triggerTime表示Alpha起作用的时间,它可由外部来触发,它和后面
的7个参数的单位均为毫秒。
    triggerTime参数后面还有7个类型为long的数,我们可以设置
这些数值,来达到我们的各种编程目的。
    前面我们介绍了VRML中各内插器节点key字段的作用,在VRML中,
key的值只能从0到1。而在JAVA3D中,Alpha输出的值不仅可以从0到1,
还可以从1到0,甚至可以先从0到1,再从1    public Alpha(int loopCount, int mod
e, long triggerTime,
            long  phaseDelayDuration,
            long increasingAlphaDuration,
            long  increasingAlphaRampDuration,
            long  alphaAtOneDuration,
            long  decreasingAlphaDuration,
            long  decreasingAlphaRampDuration,
            long  alphaAtZeroDuration)
    Alpha构造函数里的头三个参数我们已经介绍过了,我们在这里介绍
它的后7个参数,它们用于定义各内插对象的周期变化方式。
    Alpha将每一个周期分外5个时段:
        起始延迟时段
        上升时段
        高位时段
        下降时段
        低位时段
                   ------
                /         \
               /           \
              /             \
       -------               -------
    每个周期的时间长度为这5个时段时间长度之和。
    每一个Alpha都必须给出这5个时段,当然,其中的任何数都可以为0,
因而我们可以获得各种各样的Alpha类型。下面我们给出部分类型:
1. 只有上升时段的类型
       /   /   /
      /   /   /
     /   /   /
    /   /   /
    这种类型的Alpha输出的数值从最小升到最大,然后又从最小升到最大。
    我们将前面的Pos.java改成这种类型时,生成的Alpha应为:
      Alpha xtranAlpha = new Alpha(-1,
                          Alpha.INCREASING_ENABLE,
                          0, 0,20000, 0, 0,0, 0, 0);
    它使形体从左移到右,再将形体跳回到左边。
2. 只有下降时段的类型
   \   \   \
    \   \   \
     \   \   \
      \   \   \
    这种类型的Alpha输出的数值从最大降到最小,然后又从最大降到最小。
    我们将前面的Pos.java改成这种类型时,生成的Alpha应为:
      Alpha xtranAlpha = new Alpha(-1,
                          Alpha.DECREASING_ENABLE,
                          0, 0,0, 0, 0,20000, 0, 0);
    它使形体从右移到左,再将形体跳回到右边。
3. 上升加高位时段的类型
     ---    ---
    /      /
   /      /
  /      /
 /      /
   这种类型的Alpha输出的数值从最小升到最大,暂停一段时间,
然后又从最小升到最大。
    我们将前面的Pos.java改成这种类型时,生成的Alpha应为:
      Alpha xtranAlpha = new Alpha(-1,
                          Alpha.INCREASING_ENABLE,
                          0, 0,10000, 0, 10000, 0,0, 0);
    它使形体从左移到右,暂停一段时间,再将形体跳回到左边。
4. 下降加低位时段
\       \
 \       \
  \       \
   ----    ----
    这种类型的Alpha输出的数值从最大降到最小,暂停一段时间,
然后又从最大降到最小。
    我们将前面的Pos.java改成这种类型时,生成的Alpha应为:
      Alpha xtranAlpha = new Alpha(-1,
                          Alpha.DECREASING_ENABLE,
                          0, 0,0, 0, 0, 10000,0, 10000);
    它使形体从右移到左,再将形体跳回到右边。
5. 暂停、上升加高位时段的类型
         ----
        /
       /
      /
     /
----
   这种类型的Alpha输出的数值一开始先暂停,然后从最小升到最
大,再暂停一段时间。不过要注意的是,这种类型不能用于
循环方式。
    我们将前面的Pos.java改成这种类型时,生成的Alpha应为:
      Alpha xtranAlpha = new Alpha(1,
                          Alpha.INCREASING_ENABLE,
                          0, 5000,10000, 0, 5000, 0,0, 0);
    它使形体暂停一段时间,从左移到右,再暂停一段时间。
6. 暂停、下降加暂停时段的类型
----
    \
     \
      \
       ------
   这种类型的Alpha输出的数值一开始先暂停,然后从最大升到最
小,再暂停一段时间。不过要注意的是,这种类型也不能用于
循环方式。
    我们将前面的Pos.java改成这种类型时,生成的Alpha应为:
      Alpha xtranAlpha = new Alpha(1,
                          Alpha.DECREASING_ENABLE,
                          0, 0,0, 0, 5000, 10000,0, 5000);
    它使形体暂停一段时间,从右移到左,再暂停一段时间。
7. 5种时段均有的类型
           -----
         /       \
        /         \
       /           \
  -----             -----
    此种类型的Alpha输出的数值一开始先暂停,然后从最小升到
最大,再暂停一段时间,然后下降到最小,最后再暂停一段时间。
不过要注意的是,这种类型也不能用于循环方式。
   我们将前面的Pos.java改成这种类型时,生成的Alpha应为:
     Alpha xtranAlpha = new Alpha(1,
        Alpha.DECREASING_ENABLE|Alpha.INCREASING_ENABLE,
        0, 3000,5000, 0, 3000, 5000,0, 3000);
8. 上升、暂停、下降、暂停类型
        ----            ----
       /    \          /    \
      /      \        /      \
     /        \------/        \-----
    本类型和第7种很相似,但没有上升前的暂停阶段,因而可以
用于循环方式。
    我们将前面的Pos.java改成这种类型时,生成的Alpha应为:
      Alpha xtranAlpha = new Alpha(-1,
          Alpha.DECREASING_ENABLE|Alpha.INCREASING_ENABLE,
          0, 0,5000, 0, 5000, 5000,0, 5000);
9. Alpha的加速
    前面介绍的8种类型,可以用于各种场合,如开关门等。但它们
均有一个问题,即形体从静止到运动的变化是跳跃性的,变化时的
加速度为无穷大。为此,JAVA3D还提供了两个参数,解决这个问题,
这就是Alpha里的increasingAlphaRampDuration和
decreasingAlphaRampDuration,它们有两种应用方式:一是设置为
大于或等于0.5,一是设置为小于0.5。
    当它们的值为第一种情况时,计算机自动将其转成0.5,使Alpha
产生的加速度在头一半时间是均匀加速的,在后一半时间里是均匀
减速的,因而在头一半时间里,加速度是正数,在后一半时间里,
加速度是相同的负数(请参考JAVA3D的API说明)。
    第一种情况在某一时段的速度图:
            /\
           /  \
          /    \
         /      \
    下面我们给出这样一个Alpha的例子:
     Alpha xtranAlpha = new Alpha(-1,
          Alpha.DECREASING_ENABLE|Alpha.INCREASING_ENABLE,
          0, 0,5000, (long)0.5, 5000, 5000,(long)0.5, 5000);
    当这两个数小于0.5时,Alpha只在时间段的两头产生加速度,
中间的加速度为0,因而中间的速度保持不变。
   下面我们给出这样一个Alpha的例子:
     Alpha xtranAlpha = new Alpha(-1,
          Alpha.DECREASING_ENABLE|Alpha.INCREASING_ENABLE,
          0, 0,5000, (long)0.2, 5000, 5000,(long)0.2, 5000);
    第二种情况在某一时段的速度图:
           --------
          /        \
         /          \
        /            \
--

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