Java 3D API官方教程
click here!!
目录
1 第一章、入门
1.1 什么是Java 3D API?
1.2 Java 3D API
1.3 构建场景图
1.3.1 高端Java 3D API的类层次
1.4 编写Java3D程序的一般步骤
1.5 一些Java 3D术语
1.6 简单方法示例: Hello
1.6.1 Hello中所用到的类
1.7 旋转立方体
第一章、入门
本章目标:
学习了本章之后,你能:
•能用一些基本术语解释什么是Java3D
•能描述出Java3D程序的基本结构。
•能识别出Java3D API中的许多类。
•能编写出简单的Java3D动画程序。
Java 3D API是一个用于编写显示和交互操作三维图形对象的程序的接口。Java 3D也是在Java2 Java开发包
(JDK)上的标准扩展。这个API提供了用于创建和操纵3D图形的高端构成方法以及渲染该图形的一些数据结构。
Java3D 提供了创建图片、可视化、动画以及3D交互图形应用程序的函数。
1.1 什么是Java 3D API?
Java 3D API是作为复杂三维图形和声音渲染系统的接口的一系列层次的JAVA类的统称。
程序员可以用Java3D开发创建和操纵3D图形对象的高端应用。这个图形对象处于一个被渲染了的虚拟世界
(VirtualUniverse)中。这个API就是用设计来用于灵活方便地创建精确的各种大小的虚拟环境,可以大到大空物体,小到
比原子还小。
除了这些功能之外,API的使用也很直接,API能自动处理渲染的细节,由于利用了Java线程机制的优势,所以Java3D的
渲染器的工作是并行进行的。并且渲染器也能自动地优化并提高渲染性能。
一个Java3D程序创建了Java3D对象的实际,并将其置之于场景图数据结构中。在这个场景图中,所有3D对象用完全指定
了虚拟世界内容和其如何被渲染的树形结构存储,Java3D程序能写成能独立运行的应用程序,或者写成能嵌入在浏览器中运
行的Applets,或者二者兼备。
1.2 Java 3D API
每一个Java3D 程序至少部分地集成了来自Java类层次中的对象,这些对象的集合称做虚拟世界(virtual universe),
这就是将要被渲染的对象。此API在javax.media.j3d包中定义了超过100多个类,这些类我们平常称做Java3D核心类。
在Java3D API中有数以百计的属性和方法。尽管如此,一个包含动画功能的简单的虚拟世界的构建仅仅需要几个类就行。
本章讨论了用尽少的对象集合和交互来渲染一个简单虚拟世界。
本章包含了一个简单但是完全的叫Hello的程序的开发过程,这个程序显示了一个能旋转的立方体,这个示例程序
是逐步开发完成的,因此这个程序用了很多版本来展示Java 3D编程过程中的每一部分。本教程中的所有程序都可以
获得电子的版本。更多的信息请见前言中的"获得本教程"[http://java.sun.com/products/java-media/3D/collateral/]。
除了Java3D核心包之外,Java3D程序设计也会用到其它的包,比如com.sun.j3d.utils,这个包通常称做Java3D工具
类,核心类中仅仅包含了在Java3D编程中必段的最底层的类,而工具类是对核心类方便而强大的补充。
工具类主要分为四类:内容加载器、场景图构建辅助类、图形类和方便的一些工具类。将来还有一些功能,比如nurbs
[non-uniform rational B-spline,非均匀有理B样条],也会加到工具类,而不是Java3D核心包中。而一些工具类在
Java 3D API 将来的版本中也可能会移到核心包中去。 利用工具类大大地减少了Java3D程序中的代码行数。除Java3D
核心类和工具类包之外,每一个Java3D程序还引用了java.awt包和javax.vecmath包中的类. java.awt包就是Abstract
WindowingToolkit (AWT). AWT类用于创建显示和渲染场景和窗口。而javax.vecmath包则定义了对点、矢量、矩阵以及
其他数学对象进行数学运算的类。
在接下来的教程中,可视对象(visual object)就是场景图中的对象比如一个立方体或者球体。对象(object)则
是指一个类的实例。而内容(content)指的是一个场景图中全部的可视对象。
1.3构建场景图 一个Java3D的虚拟世界创建自一个场景图,而场景图就是由Java3D类的实例构建而成.场景图集成了定义图形、声音、
光线、位置、方向以及可视物体和声音对象的表面属性等对象。 一个通常的图形定义是一个由结点和弧边组成的数据结构。一个结点是一个数据元素,而边则是数据元素之间的关系。场景图中的结点就是Java3D类的实例,而边展示了这些Java 3D实例之间的两种关系。最为通用的关系是就是父子关系(parent-child relationship),一组结点可以有任意数目的孩子却只能有一个双亲。一个叶子结果可以有一个双亲但是没有孩子。
另一个关系是引用(reference)。一个引用与场景图结点中的结点组件(NodeComponent)对象相关联。结点组件定义了用于渲染可视对象的图形和表面属性。
Java 3D场景图就是由一堆具有父子关系的结点构建成的树形结构。在树形结构里,其中有且仅有一个结点是根结点,共他结点都可以顺着从根开始的弧边可以访问到,树形结构中的结点是没有回路的。一个场景图就是由植根于本地(Locale)对象的树而形成的。结点组件和引用弧边都不是场景图树的组成部分。
在树形结构中,从根结点到叶子结点有且仅有一条路径,因此,从场景图的根到其每个叶子结点也仅有一条路径。从场景图根结点到到特点叶子结果的路径我们称之为该叶子结点的场景图路径(scene graph path)。因此,一条场景图路径恰恰只通向了一个叶子结点。而在场景图中从根到每个叶子结点都有一条这样的路径。在Java3D场景图中的每一条场景图路径也完全地定义了路径的叶子的状态信息。状态信息包括位置、方向、可视对象的大小。由此可见,每一个可视对象的可视属性仅仅由其场景图路私决定。Java3D渲染利用这点,以仅可能有效地按它所定义的顺序来渲染叶子对象。Java 3D程序员一般情况下不用控制渲染对象的顺序。[原注:Java3D 程序员仅仅可以用来控制渲染对象顺序的是OrderedGroup类结点,在本教程中对此部分未加论述,请参见Java3D API规范文档]
在树形结构中,从根结点到叶子结点有且仅有一条路径,因此,从场景图的根到其每个叶子结点也仅有一条路径。从场景图根结点到到特点叶子结果的路径我们称之为该叶子结点的场景图路径(scene graph path)。因此,一条场景图路径恰恰只通向了一个叶子结点。而在场景图中从根到每个叶子结点都有一条这样的路径。在Java3D场景图中的每一条场景图路径也完全地定义了路径的叶子的状态信息。状态信息包括位置、方向、可视对象的大小。由此可见,每一个可视对象的可视属性仅仅由其场景图路私决定。Java3D渲染利用这点,以仅可能有效地按它所定义的顺序来渲染叶子对象。Java 3D程序员一般情况下不用控制渲染对象的顺序。[原注:Java3D 程序员仅仅可以用来控制渲染对象顺序的是OrderedGroup类结点,在本教程中对此部分未加论述,请参见Java3D API规范文档]
场景图的图形表示可以当作设计工具或者Java3D程序的文档。场景图一般用一些标准的图形标记来绘制,如图1-1所示。Java 3D程序可能不止有包含场景图中的这些对象。
可以用以上标志集合来设计一个Java3D虚拟世界场景图。等设计上的事情完成后,场景图的设计就是程序设计的规范。等到程序也设计完成,同一个场景图就是程序的精解表现(假设程序是依照设计的图来进行的话)。一个从已有程序绘制成的场景图可以做创建程序场景图的文档。
可以用以上标志集合来设计一个Java3D虚拟世界场景图。等设计上的事情完成后,场景图的设计就是程序设计的规范。等到程序也设计完成,同一个场景图就是程序的精解表现(假设程序是依照设计的图来进行的话)。一个从已有程序绘制成的场景图可以做创建程序场景图的文档。
VirtualUniversee和Locale类的对象,下面的三个则常常用于标注特定对象[译者注:Group子类的对象等]的子类,最后一个标记用于表示其它类的对象。实线箭头表示两个所连接的对象之间存在父子关系。而虚线箭头则表求一个对象是另一个对象的引用。引用的对象可以供一个场景图中的不同的分支所共享。
在平时,创建一个错误的场景图也是可能的,场景图之所以不合理是因为它与有向无环图(Directed Acyclic Graph Or DAG)的规则相冲突.问题存在于两个TransformGroup对象都以同样的Shape3D叶子对象作为其孩子。请记住,一个叶子结点只能一个双亲,也就是,从Locale对象到叶子结点只能有一条路径(或者从叶子结点到Locale对象只能有一条路径)。你也许会认为,图1-3图所示的场景在虚拟世界中定义了三个可视对象。它看起来好像是这个场景图通过重用图形右边的可视对象(Shape3D)而定义了两个对象。从概念上讲,每一个TransformGroup 对象都作为共享的那个Shape3D的双亲,这个Shape3D的可视化对象可以允许在不同地方放置一张图片。尽管如此,由于父子边之间的关系构不成树形结构,所以这个场景图是不合法的。在这个例子中,表现为Shape3D对象有多于一个以上的双亲。对树形结构和有向无环图的讨论是正确的,然而,Java 3D运行时系统会报告这类父子关系之间的错误。树形结构存在的限制是每一个Shape3D 对象只能有一个双亲。,‘多亲'异常会在运行时报告出来。这种不合法场景图的解决办法,每一个Shape3D只有一个双亲。一个定义了不合理(法)场景图的Java3D程序可能通过编译,但是不会在运行时渲染。当一个定义了不合法场景图的Java3D程序运行时,Java3D系统会检测到这个问题,从而会报告一个异常。程序还会继续运行,但是结果是,应该被关闭,没有任何渲染好的图象生成。每一个场景图有一个唯一的VirtualUniverse,这个VirtualUniverse有一系列 Locale 对象。 一个Locale对象,提供了虚拟世界中的一个参考点。可以把Locale对象看作是在虚拟世界中定义可视对象位置的标
志。一个Java3D程序有多于一个的VirtualUniverse对象,技术上是可行的,因此,可以在虚拟世界中定义多个Locale对象,然而,在多个虚拟世界之间没有内在的沟通方式,更进一步讲,一个场景图不能存于多个虚拟世界中。同时,我们强烈建议在一个Java 3D程序中只同时拥有有且仅有一个VirtualUniverse。而一个VirtualUniverse 可能在多个Locale对象中引用,但是更多的Java 3D程序只有一个Locale对象,每一个Locale对象,可以作为场景图中多个子图的根结点。参考图1- 2作为场景图的例子,注意到图中的Locale对象有两个子图分支。 一个BranchGroup对象是子图的根结点,或者是分支图的根结点。场景子图可以分为两类,视图分支图(the view branch graph)和内容分支图( the content branch graph.)。内容分支图指定了虚拟世界的内容——图形,表面,动作,位置,声音以及光线等。视图分支子图指定了视图参数比如观看位置和方向。总的来说,两类子图指定了很多渲染要完成的工作。图1-5显示了Java 3D API类层次中的前面三个层次。
1.3.1高端Java 3D API的类层次
VirtualUniverse, Locale, Group, 和 Leaf 类处于类层次中的这部分。除了VirtualUniverse 和Locale对象,场景图中余下的部分由SceneGraphObject 对象构成。SceneGraphObject 几乎是Java3D类中每一个核心类和工具类的超类 [译者注:超类即上层类,可以是父类或者祖先类]。
SceneGraphObject 有两个子类: Node 类NodeComponent.类,Node子类提供了场景图中的绝大部分对象,一个Node对象可以是一个Group,也可是一个Leaf结点对象。
Group 和Leaf是一系列类的超类。这里可以一目了然地看到Node类的子类,它有两个子类,而 NodeComponent 类,在这些背景知识介绍之后,在Java3D程序的构建中会解释到。
Node 类
Node是Group和Leaf类的一个抽象超类. Node 为其子类定义了一些公共的重要的方法。某些方法的信息会在更多的背景知识介绍了之后提到。Node 的子类构成了子图。
Group 类
Group 类是用于在虚拟世界中指定可视对象位置和方向的类的超类。Group类的两个下层类是 BranchGroup是 TransformGroup. 在场景图的图形表现中,Group标记 (用圆表示)。而其中BranchGroups注为GB, TransformGroups 注为TG,等等。具体例子请见图1-2。
Leaf 类
Leaf是用于指定虚拟世界中可视对象的形状,声音和,动作的类的超类。Leaf的一些子类如Shape3D, Light, Behavior, 和 Sound. 这些对象不能有自己的孩子,并且可能引用NodeComponents对象。
NodeComponent 类
NodeComponent 类是用于指定Shape3D (Leaf)结点对象的图形,表面,纹理和材质属性的类的超类。NodeComponents 不是场景图的组成部分,但是为其所引用。一个NodeComponent 对象可能为多个Shape3D对象所引用(同一个材质对象可以赋予多个shape3D对象)。
1.4编写Java3D程序的一般步骤
SceneGraphObject类的子类就是集成构建场景图的模块,一个Java3D程序的开发大略可以分为七步(把它们聚在一起,在Java 3D API 规范中和这里称之为步骤(recipe)),具体如下列表所示,这些方法可用于装配许多的Java3D程序。
1. 创建一个Canvas3D对象。
2. 创建一个VirtualUniverse对象。
3. 创建一个Locale 对象,并使之与VirtualUniverse相关联。
4. 构建一个视图子图。
a. 创建一个View 对象。
b. 创建一个ViewPlatform对象。
c. 创建一个PhysicalBody对象。
d. 创建一个PhysicalEnvironment对象。
e. 把 ViewPlatform, PhysicalBody, PhysicalEnvironment, 和Canvas3D对象与View 对象相关联。
5. 构建一个或多个内容子图。
6. 编译所有子图。
7. 把子图加到Locale对象中。
表 1-1 编写Java3D程序的一般步骤
这些步骤忽略了细节但是解释了Java 3D编程中的基本概念。创建场景图中的子图是编程的主要部分。但我们并没有展开这些步骤详细讨论,本教程的下一部分解释了一种用更少的代码更容易的手段来构建一个非常简单的场景图的方法。 1.4.1 编写Java 3D程序的一个简单方法
用基本方法编写具有视图分支图的Java 3D programs程序的结构有其唯一性,构建视图分支子图结构的规则可以通过SimpleUniverse工具类来实现. SimpleUniverse 的实例承担了构建场景图的基本步骤中的第2, 3以及第4步。利用SimpleUniverse类来进行Java3D编程,可以大大减少创建视图分支图的时间和精力,从而,程序员可以有更多的时间来构建内容分支子图,这才是真正与Java3D程序事关重大的。
SimpleUniverse类对于Java 3D编程而言真是一个很好的起点,因为它允许程序员暂时忽略视图子图的存在.尽管如此,SimpleUniverse 中也不允许同一个虚拟世界存在多个视图。
本教程的所有例子程序都用到了SimpleUniverse类,因此,如果程序员想获得更多的关于View, ViewPlatform, PhysicalBody, 和PhysicalEnvironment 类的信息请参考其它参考资料,附录B有详细的参考资料列表。
SimpleUniverse类 SimpleUniverse 对象的构造函数创建了包含VirtualUniverse 、Locale对象以及一个完整的视图子图在内的场景图,SimpleUniverse创建的视图子图是用了ViewingPlatform 和Viewer 便利类的实例来代替了其它核心类来创建视图子图。注意到SimpleUniverse仅仅是没有直接用到 Java3D核心类中的View和ViewPlatform对象的。SimpleUniverse 对象提供了图1-7中大方框中的所有功能。com.sun.j3d.utils.universe包包括了 SimpleUniverse, ViewingPlatform, 和Viewer convenience工具类
利用一个SimpleUniverse 对象可以使构造Java3D程序的基本步骤更加简单,表1-2展示了简单的方法。这是用SimpleUniverse 对象之后构建Java3D程序所需的步骤,上文所提到的基本步骤的第2, 3,和4步已经被本方法的第2步所替代。 1. 创建一个Canvas3D对象。
2. 创建一个SimpleUniverse对象,并添加对先前创建的Canvas3D 对象的引用。
a. 定制SimpleUniverse对象。
3. 构建内容子图。
4. 编译内容分支子图。
5. 把内容子图添加到SimpleUniverse的Locale中。
表1-2 用SimpleUniverse创建Java3D程序的简单步骤 下面的灰框中的内容是本教程中参考模块的第一次出现。参考模块一般对一个类的构造函数、方法和属性作了个列表。使用参考模块的目的在于使读者能在手头上没有其他参考资料的情况下能学到基本的Java 3D API编程知识。本教程中的参考块并没有涉及到每一个类的构造函数和方法,由于这个原因,很多的Java 3D API 类都没有列出参考块。因此,本教程的文档本不能替代Java 3D API规范的位置,尽管如此,列出了构造函数、方法和属性的参考块的这些类,本教程所提供的信息往往比Java 3D API规范所提供的信息更加详实。
SimpleUniverse 构造函数 包: com.sun.j3d.utils.universe
这个类构建了一个尽可能小的用户环境,以使Java3D程序能尽快尽简单地运转起来。这个工具类创建了视图子图中所必需的所有对象。特别是创建了Locale, VirtualUniverse, ViewingPlatform, 和Viewer对象, (构建这些对象时统统使用默认值).这些对象以恰当的关系构成了视图子图。
SimpleUniverse 提供了许多基本的Java 3D应用程序所必需的全部功能. Viewer和ViewingPlatform都是很方便的工具类.这些类用到了View 和ViewPlatform 核心类。
SimpleUniverse() 构建一个包含视图子图的简单虚拟世界。.
SimpleUniverse(Canvas3D canvas3D) 构建一个简单虚拟世界并与指定的Canvas3D对象建立关联。建一个简单虚拟世界并与指定的Canvas3D对象建立关联。
SimpleUniverse对象创建了虚拟世界中一个完全的视图分支子图。这个视图分支图包括一个图板(image plate)。Java
3D把场景内容投影到图板块上形成一个渲染图象。Canvas3D 对象,提供了在计算机的窗口上显示图象,就可以看做图板。
图1-9,显示了图象图板,观察者位置和虚拟世界的关系。 观察者在图板后面。而可视对象在图板之前并能在图板上进行渲染。渲染就可以看作是可视对象到图板上的投影。这个观点就如图中的四个方向上的投影仪(虚线所示)
默认地,图板位置SimpleUniverse原始位置的中心,默认的方向是从Z轴从上往下看的。从这个位置上看,X轴是一条正向在右边的水平穿过图板的直线,而Y轴是垂直穿过图板中心、正向在上方的直线。因此,点 (0,0,0)就处于图板的正中央。 一般的Java3D程序,都把视图往后退(Z轴正向)(译者注:物体前移,往Z轴正向移,或往图外移),以使物体处于或者离原始视图比较近。SimpleUniverse类有一个ViewingPlatform的类的实例作为成员对象,ViewingPlatform类也有一个setNominalViewingTransform的方法来设置观察者(眼睛)的位置,使之位于 (0, 0, 2.41)(looking in the negative z direction toward the origin?).
ViewingPlatform setNominalViewingTransform() 方法
包: com.sun.j3d.utils.universe ViewingPlatform 类用于设置SimpleUniverse 对象中Java 3D场景图的视图分支图。这个方法一般用SimpleUniverse 类的getViewingPlatform方法来进行连接。
void setNominalViewingTransform() 把SimpleUniverse对象中的象征性的观察者设置约2.41米的距离变化。在这个距离上,视图的默认属性,2米高和宽的对象大约都会恰好与图板符合。
创建了Canvas3D和Simple Universe对象后,下一步就是创建内容子图。对视图子图中的常规结构的应用,从而导致应用SimpleUniverse类的这一套,对内容子图并不适合,因为内容子图在每一个程序中都各有不同,因而也就不可能给出构建一个内容子图的通用的详细方法。这也意味着你想集成的任何虚拟世界中并不存在简单内容类("simple content")。 创建内容子图是第1.6,1.7和1.9节的主题,在1.8节中讨论了内容了图的编译。如果你迫不及待地想看代码以找出个究竟,请参考代码段1-1,这就是一个应用SimpleUniverse 类的例子。
创建了内容子图之后,可以用addBranchGraph把内容子图加到SimpleUniverse对象中. addBranchGraph方法把BranchGroup 的实例作为唯一的传入参数。BranchGroup作为SimpleUniverse 对象所创建的Locale对象的孩子加到场景图中。
SimpleUniverse 的方法 (只列出了部分) 包: com.sun.j3d.utils.universe
void addBranchGraph(BranchGroup bg) 用于往SimpleUniverse对象所创建的Locale对象的场景图中。用这个方法把内容子图添加到虚拟世界中。
ViewingPlatform getViewingPlatform() 用于获取SimpleUniverse 实例化后的ViewingPlatform 对象。这个方法再附加调用setNominalViewingTransform()方法来调整视图的位置。
1.5一些Java 3D术语
开始创内容分支图的主题之前,我们先定义两个Java3D的术语. 即live 和 compiled . 把一个分支图插入到Locale就使Locale被激活。结果,分支图中的每一个对象都是活的。一个对象如果变活会导致一些结果。激活的对象就是要被渲染的对象。同时,激活的对象的参数一般是不能修改的,除非相应的能力(capability)在对象成为激活的对象之前就已经特定地设置好了。与能力相关的知识第1.8.2节也作了讨论。 BranchGroup 对象都是可以编译的(compiled)。 编译一个BranchGroup 可以把一个BranchGroup对象和其所有祖先变成一种渲染器所能更高效地渲染的格式。推荐编译一个BranchGroup对象在使之变为活对象之前的最后一步进行,并且最好只编译一遍插入Locale中的所有BranchGroup。在1.8节和1.8.1节更进一步讨论了编译问题。
BranchGroup compile() 方法 void compile() 通过创建和缓存一个编译过的场景图来把与这个对象相关联的源BranchGroup进行编译。
编译和变活的概念是SceneGraphObject中实现的。与这些概念相关的SceneGraphObject 类的两个方法在SceneGraphObject的方法的参考框中得到说明。
SceneGraphObject 方法 (部分列出) SceneGraphObject几乎是Group中创建场景图的每一个对象的超类。包括Leaf和NodeComponent。SceneGraphObject 为其子类提供了一些通用的方法和属性。这里说明了两个。SceneGraphObject的方法是与"编译"关联的,在第1.8节讲到了一些基本的东西。 boolean isCompiled() 返回一个布尔型标记,表时场景图中的结点是否已经编译过。 boolean isLive() 返回一个布尔型标记,表时场景图中的结点是否已经被激活。
注意在基本和简单的方法中都没有"启动渲染器"这一项。当一个包含了视图实例的分支图在虚拟世界中被激活的时候,Java 3D 渲染器开始以无限循环的方式运行。一旦启动,Java 3D渲染器在概念上来讲就执行如下伪码中的操作。 while(true) { //永远执行 Process input //处理输入 If (request to exit) break //如果程序要求 Perform Behaviors //执行交互动作 Traverse the scene graph //遍历场景图以渲染各个可视对象 and render visual objects } Cleanup and exit //清理退出
上一节讲述了在没有内容分支图时构建一个简单的虚拟世界,而创建内容子图是下面几节的主题,对创建内容子图的讲述是通过示例程序来进行的。
简单方法示例: Hello
典型的Java 3D程序以定义一个扩展Applet类的新类作为起始,示例的程序文件Hello.java 可以在 examples/HelloJava3D 目录中找到。Hello这个类扩展了 Applet类。一些Java3D程序写成应用程序,但是用 Applet也可以有很容易的方法使之转型成为带有窗口的应用程序。
Java 3D程序的主类一般都定义一个方法来构建内容分支图。在Hello示例中,就定义了这样的方法,并声明为 createSceneGraph ()。用简单分法所创建场景图的全部步骤都在Hello 构造函数类中得到了实现。
第1步、创建一个Canvas3D对象。具体见程序的第4行到第6行。
第2步、创建一个SimpleUniverse对象,是在第13行。.第2a步, 定制SimpleUniverse 对象,到第17行就完成了.
第3步,构建内容分支图,就是通过调用createSceneGraph()方法来完成的。
第4步,编译内容子图,代码见第 10行。
最后第5步,把内容子图插入到SimpleUniverse的Lacale中,这个操作见第19行。
1. public class Hello extends Applet {
2. public Hello() {
3. setLayout(new BorderLayout());
4. GraphicsConfiguration config =
5. SimpleUniverse.getPreferredConfiguration();
6. Canvas3D canvas3D = new Canvas3D(config);
7. add("Center", canvas3D);
8.
9. BranchGroup scene = createSceneGraph();
10. scene.compile();
11. 12. // SimpleUniverse类是一个很方便的工具类
13. SimpleUniverse simpleU = new SimpleUniverse(canvas3D);
14.
15. // 这把ViewPlatform往后移一点点,
16. //以使场景中的对象能被看到。
17. simpleU.getViewingPlatform().setNominalViewingTransform();
18.
19. simpleU.addBranchGraph(scene);
20. } // Hello (构造函数)结束
//代码段1-1 Class Hello
/**简单方法的第3步是创建内容分支图。创建内容分支图的具体代码见代码段1-2. 这也可能是再简单不过的内容分支图了。在代码段1-2中创建的内容分支图包括了一个静态的图形对象,即带有颜色的立方体。这个带色立方体位于虚拟世界坐标系统中初始位置。按照视图提供的位置和方向,那个渲染后的立方体看起来像一个矩形。具体效果如图1-12所示。 */
1. public BranchGroup createSceneGraph() {
2. // 创建分支子图的根结点
3. BranchGroup objRoot = new BranchGroup(); 4. 5. // 创建一个简单的图形叶子结点,并把其加到场景图中
6. // ColorCube也是一个很方便的工具类
7. objRoot.addChild(new ColorCube(0.4)); 8. 9. return objRoot;
10. } // Hello 的创建场景图的方法createSceneGraph结束
11. } // Hello类结束
/**代码段1-2 Hello 类的用于创建场景图的createSceneGraph方法
Hello类是从Applet类继承而来的,但是这个程序由于运用了MainFrame类也是可以作为应用程序独立运行的。
Applet 类是用于写在窗口式的易于运行的Java 3D程序的基本类。MainFrame 提供了一个AWT 框架(frame )(即窗
体) ,以使applet能嵌入从而像应用程序一样运行。 结果程序的窗口的大小是在运用MainFrame类构建时时候指定的。代码段 1-3 说明了Hello.java中所用到的MainFrame 类的用法。
MainFrame 构造函数 (列出部分)
包: com.sun.j3d.utils.applet MainFrame 类把一个小程序Applet转换成一个应用程序。从而继承自applet类的对象调用了MainFrame构造函数后都有一个 main()方法。MainFrame扩展了java.awt.Frame类并且实现了java.lang.Runnable, java.applet.AppletStub, 和java.applet.AppletContext. MainFrame 类是受版权保护的,由Jef Poskanzer 在1996-1998到年间创建。Email: jef@acme.com http://www.acme.com/java/ MainFrame(java.applet.Applet applet, int width, int height)
创建一个MainFrame对象,以使一个Applet能作为一个应用程序独立运行。参数: applet - 继承自applet类的构造函数。MainFrame为applet提供了一个AWT框架。 width - 窗体宽度象素值。 height - 窗体高度象素值。 */
1. // 下面的代码允许Applet程序结果
2. //作为应用程序运行。
3.
4. public static void main(String[] args) {
5. Frame frame = new MainFrame(new Hello(), 256, 256);
6. } // main结束 (Hello的方法)
代码段1-3 Hello 类的Main()方法调用MainFrame
前面的三个代码段 (1-1, 1-2, and 1-3)再加上相应的import语句就组成了一个完整的Java3D应用程序。以下import语句在编译Hello这个类时是必须的。
Java 3D编程所用到的最常用的类在包javax.media.j3d或者 javax.vecmath中,在这个例子里, ColorCube工具类就在包com.sun.j3d.utils.geometry中. 从而,大多数Java 3D程序都会有代码段1-4中除引入ColorCube类之外所示的import 语句。
1. import java.applet.Applet;
2. import java.awt.BorderLayout;
3. import java.awt.Frame;
4. import java.awt.event.*;
5. import com.sun.j3d.utils.applet.MainFrame;
6. import com.sun.j3d.utils.universe.*;
7. import com.sun.j3d.utils.geometry.ColorCube;
8. import javax.media.j3d.*;
9. import javax.vecmath.*;
//代码段 1-4 Hello.java的import语句
在Hello.java示例程序中,在唯一的locale对象中放置了唯一的图形对象。这个场景图如图1-11所示。
前面四个代码段 (1-1, 1-2, 1-3, 与 1-4) 组成了完整的示例程序Hello.java文件。用命令javac Hello.java来编译代码,用java Hello来运行代码。运行结果如图1-12所示。
而在Hello示例中不是每一行代码我们都进行了解释。如果通读了整个示例,集成Java3D程序的基本概念应该清晰明了了。下面这一小节通过说明上面程序中所用到的类来弥补了说明不足的缺陷。为了更进一步了解Java 3D API 和 Hello程序,Hello例子中所用到的每一个Java 3D API类在这里都作了一个说明。BranchGroup 类
这种类型的对象是用于构建建场景图的, BranchGroup的实例是子图的根结点, BranchGroup对象也是唯一能成为Locale对象的孩子对象的对象。BranchGroup对象可以有多个孩子, BranchGroup对象的孩子对象可以是Group和Leaf对象。
BranchGroup 默认构造函数
BranchGroup()
BranchGroup的实例,作为场景图分支的根结点,BranchGroup 对象也是能唯一插入到Locale对象中的对象。
Canvas3D类
Canvas3D 类继承自Abstract Windowing Toolkit