您的位置:首页 > 编程语言 > Java开发

Java 3D API官方教程[翻译四]

2007-09-04 11:13 387 查看
Java 3D API官方教程[翻译四]
代码段1-5在场景图中集成了一个TransformGroup对象,使立方体能沿X轴旋转。这个旋转变换的创建的第一步是构造Transform3D对象rotate创建。 代码第6行构造了Transform3D 对象。而在第8行,用rotX方法指定了这个旋转变换。第10行利用已有的旋转变换构造了TransformGroup对象。
在旋转变换中指定了两个参数:一是旋转所依赖的坐标轴,二是旋转的角度。坐标系的指定是通过选定合适的方法来进行的。而旋转的角度是通过指定所调用方法的参数来确定的。

因为旋转角度的指定是用弧度来表示的,所以PI/4就是1/8个圆,也就是45度。

创建了Transform3D 对象rotate之 后,它便用于构造TransformGroup对象objRotate, (如第10行代码所示).Transform3D对象没有在场景图中用到(原文是The Transform3D object is used in the scene graph.译者认为有误)。 objRotate 对象然后把把ColorCube对象作为其孩子(见代码第11行),与其相同,objRoot对象也把objRotate 作为其孩子(代码第12所示)。
Transform3D类中的方法rotX(), rotY,和rotZ()在上一节的参考框中都有说明。

1. public BranchGroup createSceneGraph() {

2. // 创建内容分支图的根结点

3. BranchGroup objRoot = new BranchGroup();

4.

5. // rotate对象复合了变换矩阵。
6. Transform3D rotate = new Transform3D();

7.
8. rotate.rotX(Math.PI/4.0d);

9.

10. TransformGroup objRotate = new TransformGroup(rotate);

11. objRotate.addChild(new ColorCube(0.4));

12. objRoot.addChild(objRotate);

13. return objRoot;

14. } // createSceneGraph方法结束

代码段1-5 内容分支图中的一个旋转变换
现在在场景图路径中,内容分支图包含了一个对应ColorCube对象的TransformGroup 对象。此场景图路径中的每一个对象都是必须的, BranchGroup对象是唯一一个能以一个Locale对象作为其子结点的对象。TransformGroup对象是唯一一个能改变位置,方向和可视 对象大小的对象。在这种例子中, TransformGroup对象改变了对象的方向,当然,ColorCube对象是提供可视对象所必须的。这个内容分支图由代码段1-5构造,其场景图 说明如图1-13所示。



代码段1-5不是示例程序目录下一个独立的程序,它只是作为里程碑展示了通往开发更大,更有趣的程序的方法。更大的问题,将在下面的小节中讲到,它在一个TransformGroup对象中组合了两种变换。

1.7.1组合图形变换示例: HelloJava3Db

通常地一个可视对象要平移和旋转,或者同时围绕两个坐标系旋转。在上面的每一种情况中,一个可视对象都要指定两种不同的变换。这两种变换会组合在同一个变换矩阵之中,并由同一个TransformGroup对象持有。代码段1-6说明了这种复合变换的用法。

在示例程序HelloJava3Db中,组合了两种旋转变换,同时构造两种旋转变换需要组合两个旋转的Tranform3D对象。这个例子中,立方体围绕 X轴和Y轴旋转。两个Transform3D对象,每个旋转变换都创建了一个(见代码段第6行和第7行)。两个Transform3D对象都分别指定了变 换(见代码第9行和第10行)。(The individual rotations are specified for the two TransformGroup objects (lines 9 and 10),原文有误,译者认为). 然后这个两个变换通过两个Transform3D对象的相乘而组合(见代码第11行)。组合后的变换然后被加载到TransformGroup对象中(见 代码第12行).

1. public BranchGroup createSceneGraph() {

2. // 创建分支子图根结点

3. BranchGroup objRoot = new BranchGroup();

4.

5. // 复合变换矩阵的rotate对象

6. Transform3D rotate = new Transform3D();

7. Transform3D tempRotate = new Transform3D();

8.

9. rotate.rotX(Math.PI/4.0d);

10. tempRotate.rotY(Math.PI/5.0d);

11. rotate.mul(tempRotate);

12. TransformGroup objRotate = new TransformGroup(rotate);

13.

14. objRotate.addChild(new ColorCube(0.4));

15. objRoot.addChild(objRotate);

16. return objRoot;

代码段1-6 HelloJava3Db中两个旋转变换的复合代 码段1-5或者是1-6都可以代替HelloJava3Da类中代码段1-2的位置来构造一个新的程序。代码段1-6在 HelloJava3Db.java文件中. 复合旋转变换的完整的示例程序在目录examples/HelloJava3D/中的HelloJava3Db.java里.这个程序也能像 HelloJava3Da一样独立运行。HelloJava3Db.java文件所关联的场景图如图1-14所示.视图分支图的创建方法如同在 HelloJava3Da中一样,用SimpleUniverse类构建,在场景图中用一个大星号来代替。现在在场景图路径中,内容分支图包含了一个对应 ColorCube对象的TransformGroup 对象。

1.8.1编译内容
BranchGroup对象有一个compile方法,调用这个方法可以把分支组下的所有分支图变为分支图的Java 3D内部表现。除了这种转换之外,内部表现在一到多个方面进行了优化。
可能的优化方法并没有在Java 3D API中指定,尽管如此,也可以有不少方法来提高效率。一个可能的优化方法就是把TransformGroups与场景图路径组合起来。例如,如果一个场景图在一个父亲-孩子关系中有两个TransformGroup对象,则其可以用一个TransformGroup 对象来表示。另一可能的方法就是如果有存在一个静态物理关系的话就可以整合中Shape3D对象中。这些优化的方法当能力属性未被设置时都会实行。其它优化方法也有可能被执行。图1-16展示了一个这种转换上的概念上的表现到一个更高效率的表现。场景图左边的图经过编译并且已经转换成为内部表现后,就如右边的图所示。这个图只是从概念上说明了内部表现,而不是Java 3D的实际表现。



1.8.2能力
当一个分支图被激活或者或者编译后,Java 3D 渲染系统把分支图转换成为一种更高效的内部表现方式。在把场景图转换成内部表现最有效果的是为了提高渲染性能。
把 图形变换转化为内部表现还有其它的效果。一个效果就是固定了场景图中变换和其它对象的值。除非在程序中特别地提供,不然程序在场景图对象激活之后就不再有 改变值的能力。也有一个程序要有当一个场景图对象的值在其激活之后仍可改变的能力,比如,为了创造动画效果需要动态改变TransformGroup 对象,这个,图形变换就需要在激活之后仍能改变。能被访问的参数列表(The list of parameters than can be accessed,译者认为,原文误),正如其方式一样,被称之为对象的能力(capabilities );每一个SceneGraphObject都有一系列的能力位(bit)值。这些位值决定了对象被编译或者激活之后,那些能力还是保留着的。这一系列能力往往因为类的不同而不同。
SceneGraphObject 方法 (列出部分)
SceneGraphObject 是包括Group,Leaf,和NodeComponent在内的创建场景图的每一个类的超类。1.5节说明了SceneGraphObject的一些其它的方法。
void clearCapability(int bit)
清除指定的能力位。
boolean getCapability(int bit)
获得指定的能力位,是否有能力位所指定的能力。
void setCapability(int bit)
设定对象具有指定能力位的能力。
举一个例子,当表现为一个TransformGroup对象时,如果还有能力去读取变换的值,那么,在对象被编译或者激活之前,能力就必须被设置。相似地,要在TransformGroup对象中改变变换的值,在在其被激活或者编译之前,写变换的能力就必须被设置。下面的参考框展示了TransformGroup类中非继承的能力。企图在一个没有设置相关能力的激活或编译了的对象上作能力改变会导致一个异常。在下一节中,利用时间的变化而作不同的旋转变换就创造了一个动画。为了使动画成为可能,TransformGroup对象就必须在其被激活或者编译之前设置ALLOW_TRANSFORM_WRITE能力。
TransformGroup的能力 (列出部分)
这里所列出的两个能力是TransformGroup所独有的,TransformGroup 从其祖先类Group 和 Node继承了一大堆能力,可能通过利用在SceneGraphObject类中定义的方法来设置,重设和访问这些能力。
ALLOW_TRANSFORM_READ
指定TransformGroup结点可以访问其对象的变换信息。
ALLOW_TRANSFORM_WRITE
指定TransformGroup结果表明有改写其变换信息的能力。
TransformGroup对象在其它方面的能力的控制也是像上面一样的。TransformGroup对象从其祖先类Group和 Node继承了一些能力设置, Group类的一些能力位常量如下面的参考框所示。
Group能力(更出部分)
TransformGroup从其祖先类继承了一大堆能力位。
ALLOW_CHILDREN_EXTEND
设置这个能力允许在其编译或者激活之后动态添加子结点。
ALLOW_CHILDREN_READ
设置这个能力允许Group结点的子结点的引用可以在其被编译或激活之后被读取。
ALLOW_CHILDREN_WRITE
设置这个能力允许Group结点的子结点的引用可以在其被编译或激活之后被改变。

Java 3D API官方教程:1.9添加动画动作- -

动画和交互的区别分别是行为是否是随着时间的前进而激活行为而是由用户的活动来产生对应原行为。

虚拟世界中的每一个可视对象可以用自般预定义的行为。实际上,一个可视对象可能有多种行为。为一个可视对象指定一个行为,一个程序员要创建指定那个行为的对象,把可视对象添加到场景图中,并且在场景图对象和行为对象之间建立合适的引用。
在一个有多个行为的虚拟世界中,光计算这些行为就需要大量的计算能力。因为渲染和行为都要利用相同的处理器,因此就可能行为所需计算能力会降低渲染性能。
Java 3D允许程序员来通过指定行为发生的空间边界来控制这个问题。这个边界称之为计划区域(scheduling region)。除非ViewPlatform的激活卷?(activation volume)与行为对象的计划区域相交,否则行为是不会起作用的。也就是说,(if there is no one in the forest to see the tree falling, it does not fall,译者暂时翻译不出来,容查查词典),计划区域特性使Java 3D处理具有多个行为的虚拟世界更为有高效。
(特殊图形处理器的图形渲染的效率的考虑则依赖于硬件环境和Java 3D的实现,尽管如此,也还是可能由于在虚拟世界中拥有太多的行为而导致不能快速渲染。)

一个插入器是在Java 3D核心包中一系列预定义好的行为类即Behavior类的子类的一个。
基于一个时间函数,插入器对象处理场景图对象的参数。比如,RotationInterpolator类,处理TransformGroup对象所指定的旋转来影响可视对象的旋转,这些对象就是TransformGroup的祖先类。
下图1-17枚举了用一个插入器对象指定一个动画所用到步骤。下图中的五步组成了创建插入动画行为的方法。

1. 创建一个目标TransformGroup
设置ALLOW_TRANSFORM_WRITE能力位
2. 创建一个Alpha对象(注:Alpha是Java3D中一个用于构造时间变化的函数,请看1.9.2节,或者请看集注(glossary)以获得更多的信息。)
指定alpha对象的时间参数.
3. 创建插入器对象。
让插入器对象引用Alpha对象和TransformGroup对象,定制行为参数.
4. 指定计划区域.
5. 把这个行为作为TransformGroup的子结点。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: