【转】Java3D探奇


本教程是为没有任何 3D 编程经验的 Java 程序员而编写的。我们将从一些基本的 3D 概念入手,探索如何构建一副场景图 — 用于描述我们想要渲染的场景的基本对象。然后,我们将接触 Java 3D 的一些更强大的功能。我们的重点将放在使用一些 Java 3D 实用类来开始您的编程。

预备知识 
对 3D 编程没有任何经验的程序员都可以是本教程的读者。

系统需求 
浏览器:Netscape 4.x 或更高版本, 或者 Internet Explorer 4.x 或更高版本,支持 Javas cript 。


思想

  Java 3D API 的设计是对以前流行的诸如 OpenGL 和 Direct3D 的 3D 图形 API 的重大革新(以前的 API 是同 3D 硬件设计紧密结合的低级过程性 API)。Java 3D 是一种功能强大的、面向对象的 API,它提供了许多超出我们认为作为“3D 图形 API”所能有的功能。Java 程序员可能会发现 Java 3D 编程环境非常熟悉而且易用。Java 3D 做了许多事情来为您管理图形数据,这样就使得您可以把精力集中在其它编程工作上。

  使用 Java 3D,首先要在场景图中设置所有的图形对象(也称为几何对象),场景图是一个层次模型,它包含有关场景中的对象以及如何渲染它们的全部信息。然后,将该场景图交由 Java 3D 渲染。您无须为显示数据而编写任何代码 ― Java 3D 为您完成了这项工作。通过使用内置的强大工具,您可以在一个更高的级别上进行编程。

对速度的需要

3D 程序员十分在意性能,这是有其原因的 ― 他们的应用程序往往对性能非常敏感。如果旋转的 CAD 模型没有平滑地旋转,或者 3D 应用程序用户不能够交互地抓取一个对象并移动它,用户将会立即注意到这一点。

令人欣慰的是,Java 3D 能够利用图形适配器所提供的任何 3D 加速性能。Java 3D 最终会在 JNI 层生成可以由图形卡加速的 OpenGL 调用。新工作站通常装有 OpenGL 加速适配器,因此您的 Java 3D 程序应该可以由硬件加速。

那么意义何在呢?


3D 图形将向您生活添加一个全新的维:z 维。在三维坐标(x,y,z)中,Z 指定该坐标离观察者的距离。Java 3D 使用 z 值除去远处遮住对象的不可见的表面。因为下图中的红色圆环离观察者的距离近,所以它的 z 值很小。当在渲染期间同时比较这两个圆环的 Z 值时,它将遮住蓝色圆环的一部分。

3D 对象包含在一起渲染的坐标集合(请参阅 Primitive 类)。您可以将它们渲染为点、线和多边形。游戏程序员可能想使用点来模仿怪物冲向玩家时射出的一串子弹。CAD 设计者为了看清她所设计的相当精确对象的更多细节,可能希望以线渲染。而当汽车设计者完成汽车对象的大部分设计的时候,他可以不是使用线框而是使用实心多边形的形式来渲染坐标。尽管实心多边形看起来更接近现实,但却不允许设计者方便地使用描述对象表面的基本数据。

在本教程中,我们将始终绘制多边形,因为这其中乐趣无穷。

移动对象


在创建完想显示的对象之后,我们可以使用 3D 变换来移动或缩放它们, 实际上就是让对象动起来。例如,当您玩 Quake 时,该游戏程序通过控制坏家伙的 3D 变换来表现他向您冲过来的效果。您视线的位置、方向和走向(在您被打成碎片之前!)被称为视点(viewpoint)。当您偷偷地四处寻找更多弹药的时候,变换更改您的视点。

变换在功能强大的 Transform3D 类中作为矩阵指定。Transform3D 提供许多助手函数以指定常见的变换,诸如平移、旋转和缩放。

光照和其它效果

除了指定在场景中显示什么对象之外,我们还可以通过指定光照效果来控制它们的显示方式(有关光照的更详细信息,请参阅 Light 类 )。您可以指定光照的效果类型,例如聚光灯,以及光的颜色。您还可以给您的场景指定雾化效果并且设置对象的自动行为。

材质贴图(通常称为粘贴墙纸)通常用于使场景更真实。例如,您可以使用木纹(wood grain)图像作为对象的表面来模仿橡木桌面。

几何对象不一定非得是非透明的;它们可以是透明的或半透明的。下图中的灯使用了透明和光照效果,陶器使用了材质贴图。
场景图树

Java 3D 场景图是一棵由两个部分或分支组成的树,这两个部分是:内容(content)和视图(view)。视图分支含有复杂 Java 3D 视图模型的所有细节,它还定义视点。好的事情是,对于大多数简单的应用我们都可以使用统一实用类(尤其是“正如其名称所暗示”的 SimpleUniverse 类)来处理视图管理的大多数复杂任务。

内容分支描述了您将在场景中看到什么 。它包含所有图形对象(球体、立方体或更复杂的几何对象)、用来移动它们的转换、光、行为、组节点和烟雾。我们的大多数工作将集中在内容分支。


组节点

Group 对象组成了场景图内容分支的内部节点 。您可以使用 Group 节点来将您的场景图组织成相互关联的部分。每个 Group 节点包含一些子节点,在处理该节点时将渲染这些子节点。Switch 节点和 TransformGroup 节点是特殊的 Group 节点,它允许您对场景图施加进一步的控制。

TransformGroup 节点在处理期间对它们的子节点应用 3D 变换(诸如平移、缩放或旋转),这使得您可以移动、旋转或缩放整个场景图。

Switch 节点限制在渲染期间访问哪些子节点,使您可以控制渲染场景图的哪些部分。以 Quake 为例,您可以将所有不同的武器分组到一个 Switch 节点下面,使得您可以只渲染当前使用的武器。


能力位(Capability bits)

Java 3D 将会通过尽可能地预先计算值来优化场景图的渲染。如果想在渲染场景时更改场景的某些方面,则必须使用能力位来指定以后想更改的数据。例如,使一个对象动起来需要更改影响该对象的变换。为了做到这一点,需要在 TransformGroup 中启用 ALLOW_TRANSFORM_WRITE 位,如下所示:


suzySpin.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);


在将场景图附加到空间(universe)之前,可以对它做任何想做的更改。然而,在 Java 3D 开始渲染之后,就只允许对设置了适当能力位的对象进行更改。

UglyCube 示例

。但是需要提醒的是,它确实很乏味。

UglyCube 只显示一个立方体。它摘自 Java 3D SDK 所带的示例 HelloUniverse 。在该样本中,创建了一个 Canvas3D 以在其上绘图,并创建了一个 SimpleUniverse 来为您处理所有的视图管理工作。内容分支的顶部总是 BranchGroup。我们将 cube 作为子对象添加并交给 BranchGroup 以便渲染。

当将 BranchGroup 添加到 SimpleUniverse 之后,Java 3D 将不断循环地进行渲染。稍后,我们将添加不同类型的节点,例如光和行为。

下面是该示例中的一些重要的行:


Canvas3D c = new Canvas3D(
SimpleUniverse.getPreferredConfiguration());
setLayout(new BorderLayout());
add("Center", canvas);
BranchGroup scene = new BranchGroup();
scene.addChild(new ColorCube(0.4));
SimpleUniverse u = new SimpleUniverse(c);
u.getViewingPlatform().setNominalViewingTransform();
u.addBranchGraph(scene);


看,我说过它很乏味吧。

场景图要点

SimpleUniverse 创建场景图的视图分支。 
Group 节点将分层结构加到场景图上。 
能力位允许访问场景图节点中的数据。

Primitive 类

Primitive 是用于几何对象的抽象类,这些用在场景图中的几何对象可以作为简单构件块使用。Java 3D 包括 Primitive 的几个具体子类 ― Sphere、Box、Cone 和 Cylinder ― 这些子类使得您可以无须指定许多数据就能轻松地创建基本对象。例如,当使用 Sphere 类时,您只需指定半径,然后,就会为您生成所有的顶点数据。

在本教程中我们将只使用 Primitive,以便您无须陷入必须指定所有图形数据的细节中

Shape3D 类


如果您不使用某个 Primitive 类,那么您将不得不使用 Shape3D 类来指定所有顶点数据。您可以将数据指定为三角形、四边形、直线和点。通常通过使用一些互相连接的三角形或四边形条带将球体的几何表示定义成多边形网格。

下图可以让您了解这些条带是如何合并形成网格。为了突出这些条带,对它们使用了不同的颜色。在该 Shape3D 对象中,每条三角形条带都与相临的三角形条带共享公共顶点,当渲染它们的时候就形成一个网格表面。

每顶点数据(Per-vertex data)


每个顶点至少必须有一个位置值(坐标)。除此之外,还可以为每个顶点指定其它值,如颜色值、法向矢量和材质坐标。法向矢量用于光照效果,材质坐标在通过材质贴图将材质应用到表面时使用。此外,每个顶点也可以含有 alpha 或透明度值同其颜色一起指定。

幸运的是,当使用 Primitive 类时,会为您生成顶点法线和材质坐标。我们将会探讨最常用的每顶点属性,顶点法线和方向坐标。


Apperance 对象

虽然您可以用每个顶点指定大量的数据,但是许多图形效果却是通过使用 Appearance 对象来应用的。该对象描述一个对象表面的整体属性。每个 Shape3D 和 Primitive 对象都将有自己的 Appearance 对象,并且每个 Appearance 对象都包含几个属性对象。例如,Appearance 对象可以包含 ColoringAttributes 对象和 RenderingAttributes 对象。

如您可见,有了这些不同的图形数据类型,Java 3D 应用程序一下子变得很复杂。为简单起见,我们将只讨论 Texture 和 Material 属性类。


小测验


让我们做个测验来测试一下您目前的知识。Primitive 基类用于以下项中的哪一项:

1.Java 3D 生成的高级几何对象 
2.定义球、圆锥体、圆柱体和立方体 
3.指定史前岩洞绘画 
4.1 和 2

Transform3D 类

变换允许您在场景中移动、旋转或调整几何对象的大小,也可以用来影响查看场景的方式。当进行 Java 3D 编程时,将经常使用 Transform3D 对象。Transform3D 对象代表一个变换矩阵。Transform3D 对象通常由 TransformGroup 类使用。我们将不会讨论 Transform3D 中的许多方法 ― 而仅仅是一些助手函数 ― 而且令人感到欣慰的是,我们也不用讨论线性代数。


移动、缩放以及旋转对象


让我们从 Transform3D 类中的一些助手函数着手:

setTranslation(Vector3f trans):平移(移动)对象。用 trans 参数中的 x、y 和 z 值来替换本次变换的平移值。


setScale(double scale):设置该变换的比例。使用该函数来调整对象的大小。


rotX(double angle):将旋转组件设置成绕 X 轴逆时针旋转。请注意调用 rotX() 会删除矩阵中的非旋转组件。方法 rotY() 和 rotZ() 也是非常有用的。角度以弧度指定,因此如果有必要,请使用 Math.toRadians(degrees) 将角度从度转换成弧度。

OrbitBehavior 类

OrbitBehavior 类允许您使用鼠标方便地移动视图。当用户移动鼠标时,它会平移、旋转以及缩放场景。下面的代码片段将 OrbitBehavior 添加到 ViewingPlatform 中。无需其它代码。(我们稍后将讨论界限球和行为。)


ViewingPlatform viewingPlatform = universe.getViewingPlatform();
orbit = new OrbitBehavior(canvas);
BoundingSphere bounds =
new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0);
orbit.setSchedulingBounds(bounds);
viewingPlatform.setViewPlatformBehavior(orbit);


请注意 OrbitBehavior 使用 SimpleUniverse 对象来操纵场景图的视图部分。还要注意的是,大多数 Java 3D SDK 样本都外加了 OrbitBehavior,您也应该在您的程序中这么做 ― 这将有助于移动对象并查看它们。我们将在本教程的余下部分回过头来讨论场景图的内容部分。

在 3D 空间中迷失

当您构建起场景图层次结构时,您会使用许多 TransformGroup 节点。您想绘制的几何对象将定位于图中的叶子上。将场景图的根与该几何叶子连接的节点路径上通常将有几个 TransformGroup 节点在其中。根和几何对象之间的所有变换都按顺序应用到那个形状,并且变换的顺序将会影响到几何对象的最终位置。

将您想做的每一项逻辑操作放在一个单独的 Transform3D 对象中(例如,将旋转操作放在一个对象中而将平移操作放在另一个对象中)。在渲染遍历期间当 Java 3D 遍历场景图时,会将这些变换组合在一起。

变换之间不是可互换的 ― 先旋转再平移同先平移再旋转的结果不同。下图演示了从两个不同的视点对观察到的几个 Cone 图元进行变换(圆柱代表轴)。我们将在下一页回顾生成该图的代码和这些圆锥各自的场景图构造。

TransformOrder 代码

以下是 TransformOrder.java 示例的简化程序块。其中有两个 TransformGroup 节点和一个 Cone,一个连接在另外一个下面。唯一的区别只是连接它们的次序和 Cone 的颜色。在红色圆锥中,objRotate TransformGroup 位于 objTranslate 之上,而对于黄色圆锥,平移在顶部,而旋转在下面。这意味着根节点到圆锥之间的路径上有不同的次序。以下是创建圆锥体及其变换的代码。


void rotateOnTop(){
topNode.addChild(objRotate); 
objRotate.addChild(objTranslate);
objTranslate.addChild(redCone); 
}
void translateOnTop(){
topNode.addChild(objTranslate); 
objTranslate.addChild(objRotate);
objRotate.addChild(yellowCone); 
}
void noTransform(){
topNode.addChild(purpleCone); 
}

变换要点

变换可用于指定场景中几何对象的位置。 
将 OrbitBehavior 与 SimpleUniverse 一起使用。 
使用 Transform3D 助手函数。 
为简单起见,将想做的每个逻辑操作放在一个不同的 Transform3D 对象中。

Light 类


光用于照亮场景中的几何对象。有几种不同的光类型,它们都是抽象 Light 类的子类。所有光都有一个颜色值,即开/关位,以及一个描述它照亮的场景区域的绑定对象。

在现实世界里,周围的对象被几个不同的光源照亮。从窗户射进的阳光和屋顶的灯光一起照亮了屋内的一切。两种光都会影响屋内对象的颜色和外观。在 Java 3D 中,可以通过使用多个光源来模拟实际的光照效果。


光类型


在场景中 AmbientLight 无处不在。它不发自某个特定点,也不指向某个特定方向。

PointLight 从一个指定位置向各个方向辐射,并随着距离的增加而减弱。点光源的一个例子是没有灯罩的台灯。SpotLight 是一种将光的范围限制在一个圆锥形内的点光源。聚光源的一个例子是手电筒。

DirectionalLight 的光线射向某一个特定方向,却不发自任何特定的位置。这种定向光的所有光线都平行发射。虽然从技术上说,太阳是一个点光源,但使用 DirectionalLight 可以更准确地模拟太阳光。

图中的茶壶有了环境光(您可以发现茶壶的背面也被略微照亮),和来自前面的定向光的照射。这两种光共同影响了茶壶表面的每个三角形的最终颜色。

场景图中的光


所有的 Light 节点都是场景图中的叶节点。当您创建它们时,需要指定 Bounds 对象;我们将使用 BoundingSphere。光将仅仅影响那些位于光的 BoundingSphere 所定义的空间内的几何对象,因此我们需要确保 BoundingSphere 足够大。在创建完光之后,我们将其附加到场景图的顶部 BranchGroup。光、行为和材质都在场景图的上面添加。


材质特性

材质特性描述对象如何反射光线。如果您的对象(Primitive 或 Shape3D)在其 Appearance 对象中没有 Material 对象,则即使您指定了一个光源,它也不会被照亮。您必须创建一个 Material 对象,启用 Material 对象中的光照,然后将其添加到 Appearance 对象中。Material 对象是在 Appearance 对象中保存的几个不同的属性集之一。

为了更好的理解材质特性如何影响对象的外观,请想象一颗闪闪发光的红宝石这个对象和一条红地毯。虽然它们都是红色的,但它们对光的反射却不同 ― 红宝石反射灯光的地方将发出耀眼的光芒,而地毯则会将光线散射出去。要为 Java 3D 指定这一外观差异,您最好在 Material 对象中为红宝石指定一个高 shininess 值而给地毯一个很低的 shininess 值。

下图显示了一些具有不同材质特性的球。


表面法线


表面法线是一个与该点所在表面垂直的矢量,它表示顶点所在表面的走向。在计算光照效果时,表面法线影响表面反射光的方式。表面法线和观察者的位置决定球面上的哪些地方闪亮发光或是镜面反射。

幸运的是,Primitive 类将会为您生成表面法线,因此本教程将不进一步讨论法线。


计算光照效果


Java 3D 使用表面法线来计算光照效果。因为每一顶点都要计算光照效果,因此具有许多顶点的对象看起来将更逼真。

上图中的 Sphere 对象的顶点数目由 Sphere 对象中的 divisions 参数控制。对粗糙的球体,使用的值为 9。对平滑的球,使用的值为 30,因此看起来更平滑一些。


光照和材质要点


·光位置和颜色、材质特性以及表面法线都会影响所照亮的对象的最终颜色。


·Appearance 类包含一个 Material 对象,该对象保持您的几何对象的光照状态。记住要启用 Material 对象中的光照。


·Material 类定义了您的几何对象反射光的方式。它包括环境光、散射光、反射的颜色和亮度。


·环境光源、点光源和方向光源产生不同的光照效果。请始终外加一个环境光源以确保场景中有些光。


·法线值确定表面的平面走向,使用 Primitive 类时会自动生成该值。

材质贴图

材质贴图通过增加对象表面的额外视觉细节来增强场景的真实感。

假定您想在场景中绘制一堵石头墙。您可以为每块石头、每片灰泥定义几何对象,然后将渲染所有这些对象以模拟这堵石头墙。那样做的工作量会很大。一个替代的方法是使用材质贴图。在本例中,您可以使用一个矩形对象来表示整堵墙,然后将一副石头墙的图像粘贴到该矩形上(如随 Java 3D 提供的 stone.jpg 图像)。

为了使用材质贴图,您需要指定图像,要将该图像粘贴到对象的位置,以及当图像不能和粘贴位置完全吻合时该如何处理,例如将一副矩形位图粘贴到一个非矩形多边形上。在本节的余下部分中,我们将讨论这些任务。

近年来,材质贴图硬件方面的技术进展是突飞猛进的,从而产生了相当复杂的问题,该问题已超出了本教程的范围。如果您对材质贴图的更高级的细节感兴趣,我推荐您学习 Sun 的 Java 3D 网站上的实用材质的教程。


装入材质

同光照一样,材质贴图影响整个几何对象。我们将再一次使用 Appearance 类来指定材质贴图效果。

Java 3D 简化了装入材质图像的过程。TextureLoader 类位于 Java 3D 实用类中:


TextureLoader texLoader = new TextureLoader(url,imageobserver)
appearance.setTexture(texLoader.getTexture());


为了看起来更真实,请总是将材质图像的宽度和高度设置成 2 的幂。其它的值会导致 TextureLoader 将材质压变形。

如果图像文件只有 RGB 值,而没有 alpha 值,则使用:


TextureLoader texLoader = new TextureLoader(url,new String("RGB"), imageobserver)


粘贴到图像上

既然我们已经装入了一幅材质图,我们需要指定如何将它粘贴到对象上。我们通过对每个顶点使用材质坐标来完成这一任务。材质坐标定义了对您的对象的每个多边形使用材质图像的哪一块。一个有用的类比是想象如何将包装纸包装到礼品上。

幸运的是,Primitive 类将为您生成材质坐标 ― 就象它们为计算光照生成法线一样。

如果您没有使用 Primitive 类,那么您需要自己定义材质坐标。要完成这一任务,同时在 x 和 y 方向指定介于 0.0 和 1.0 之间的值。以石头墙为例,我们需要为石头墙的每一个角指定材质坐标。假定我们要在墙壁上使用整幅石头图像,我们需要为四个角中的每个角指定一个坐标:(0,0)、(1,0)、(1,1) 和(0,1)。这会将整个石头图像在组成这堵墙的矩形中拉伸。



压缩和拉伸材质

当需要将矩形材质用于非矩形区域时,材质贴图会变得复杂。将材质粘贴到对象上时对其进行的压缩或拉伸被称为过滤。

过滤时,如果提供材质的不同尺寸的表示(小地图)供 Java 3D 使用,材质贴图看起来将更真实。

有几种方法可用于过滤材质。您可以根据显卡的性能和期望的外观来选择过滤类型。您需要做一些尝试来确定哪种方式看起来最好。

材质贴图示例


该文件使用材质贴图的 Primitive。记住 Primitive 类将生成用于定义图像在对象上的粘贴位置的材质坐标。我们的示例使用 TextureLoader 实用程序来读入一幅 jpeg 图像并生成在 MIP 贴图中所用的过滤图像。请注意如何将材质压入球的两极和圆锥的锥顶。在每一个锥体/球体对中都使用了不同的材质过滤。您可以注意到在红色条纹和白色条纹之间的边界上的过滤差别。

为了让材质装入器为您生成预过滤图像,请在构造 TextureLoader 时指定 GENERATE_MIPMAP。在您的 Texture 对象(存储在 Appearance 对象中)指定 MIP 贴图过滤函数。


材质贴图要点


·材质贴图是一个将图像粘贴到几何对象上的过程。使用每个顶点的材质坐标来控制图像的方向和在几何对象上的位置。


·使用 TextureLoader 实用程序读入图像文件,并在构造函数中指定 TextureLoader.GENERATE_MIPMAP 标志。


·无需您亲自指定材质坐标,让 Primitive 类为您生成。在构造 Primitive 时,使用 Primitive.GENERATE_TEXTURE_COORDS。


·材质贴图是一个复杂的主题。不要急于掌握所有不同的选项。刚开始时可以使用缺省值。

Behavior 类


行为允许您使场景元素动起来并同场景图交互。Behavior 类为您的代码提供了一种修改场景图的机制。Behavior 位于场景图中并由刺激,例如鼠标运动,触发。

和光一样,行为有界限和能力位,并且必须被附加到场景图上。因此,如果您的行为没有起作用,请确保界限足够大,以便启用了行为并将行为附加到场景图中。

插入器提供了一种将简单动画添加到场景图中的方法。插入器玩起来可以很有趣,并且我们将在我们的示例中使用它们。但是,首先我们将看一些 Behavior 处理的基本内容。


唤醒调用


通过 WakeupCriterion 指定触发行为的条件。唤醒条件的示例包括按键、鼠标事件、定时器以及已播放的帧的数目。在最初创建行为以及每次处理行为消息时指定条件。OrbitBehavior 是一个由鼠标事件唤醒的 Behavior 示例。

通过使用 WakeupOnElapsedTime,可以改变 TranformGroup 的 Transform3D 来使得场景图的一部分动起来。

processStimulus() 方法

当唤醒事件发生时,将调用行为的 processStimulus() 方法。您可以在 processStimulus() 方法中做任何事情 ― 可以从场景中添加或删除对象,更改变换,更改对象的外观,检测两个对象何时相撞,或者您需要做的任何其它事。

请记住无论您需要在场景图中更改什么事物,都需要设置相关的能力位。例如,要更改 processStimulus() 方法中的 TransformGroup 节点,您需要设置 TransformGroup.ALLOW_TRANSFORM_WRITE 位。


插入器


插入器是内置的,它可以帮助您将简单动画添加到场景图中。它们在您所定义的值的范围内平滑地移动或插入。

随Java 3D SDK 提供的 GearBox 示例使用几个旋转插入器来使下图所示的齿轮动起来。


每一个齿轮都对应一个每隔一定时间就会被重复触发的 RotationInterpolator。RotationInterpolator 对包含齿轮几何对象的 TransformGroup 应用旋转,从而引起该齿轮转动。


全都在计时


Alpha 对象生成一个 0.0 与 1.0 之间的值作为计时之用。(请注意Alpha 对象同顶点的 alpha 值无关,后者指定透明度。)

插入器使用 Alpha 对象来实施它们对场景图的更改。Alpha 对象的值可以随时间而改变,这取决于您如何对其编程。我们的齿轮以匀速连续不停地旋转。每当 Alpha 对象触发 RotationInterpolator 时,RotationInterpolator 使用生成的 alpha 值来计算新的旋转(即,使齿轮转动。)通过使用下面的代码,可以创建一个以匀速无限循环的 Alpha:


Alpha(int loopCount, long speed)


有大量的选项用于更改 Alpha 对象的行为。您可以对其加速,停一段时间,然后慢慢地使其停下来。

旋转示例


创建一个 Sphere ,然后将地图材质应用于其上。(地球看起来有些模糊,因为用作材质的地图不详尽。)我在 RotationInterpolator 中设置了一个 TransformGroup,然后将用材质处理过的 Sphere 附加到 TransformGroup 之下。当 Interpolator 改变 TransformGroup 时,地球开始旋转。因为 Interpolator 在渲染循环开始之后更改了场景图中的值,所以我们必须设置一个能力位:


spinGroup.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE)


在这一示例中,我将 Alpha 对象配置成加速顺时针旋转,然后反过来逆时针旋转。


颜色插入器

对于ColorInterp.java,我已经添加了代码以将颜色插入器附加到旋转的地球上。它不影响 TransformGroup,而是影响 Material 对象中的散射颜色。因为在渲染循环开始之后,Material 对象将会变化,所以我设置了其能力位。


material.setCapability(Material.ALLOW_COMPONENT_WRITE);
Alpha colorAlpha = new Alpha(-1, 2000);
Color3f endColor = new Color3f(1.0f,1.0f,1.0f);
Color3f startColor = new Color3f(0.0f,0.0f,0.0f);
ColorInterpolator colorInterp =
new ColorInterpolator(colorAlpha, mat,startColor,endColor);
colorInterp.setSchedulingBounds(bounds);

结束语


这就完成了我们的对 Java 3D 的介绍。在非常短的时间内我们讨论了很多基础知识,那么让我们对重点做一下回顾:

Java 3D 允许您开发具有高度视觉真实感的3D图形应用程序。您构建一副描述您想渲染的任何事情的场景图,包括几何对象和视觉效果。


内置 Primitive 类集允许您迅速地构建起一幅充满几何对象的场景图,而不用为诸如材质坐标和表面法线之类更复杂的细节而担心。


使用 Light 类和 Material 类描述场景的光照。


可以使用材质贴图提供额外的真实感。


插入器是一种允许将动画添加到场景中的 Behavior。 
图形编程尤其是 Java 3D 的乐趣很难用语言表达。是这里的动手上机实践吸引了您并使您爱不释手。我推荐您下载 参考资料 中的样本代码并实验各种不同的技术来看看它们的作用及其工作原理。使用不同的光照并尝试使用材质。尽情地享受乐趣吧!


参考资料 
Java 3D 网站,该站点包含大量的有用信息,包括一些极好的教程。

下载用于本教程的()的源代码样本。

访问 Sun 的

Java 3D 社区网站提供综合性的资源并包括解答您在使用这些复杂的 API 时可能碰到的常见问题的 FAQ。

NCSA Portfolio是用于 3D 程序的实用对象集。其中还包含库中对象的完整文档以及演示如何使用这些对象的示例源代码。

访问 Web3D 联盟网站以获取 VRML 详细信息。

Java 3D AIX 版,目前包含在 IBM Java Developer Kit AIX 版 中,是用于 3D 图形的场景图 API,该 API 扩展了核心 Java API,它允许您轻松地将高质量、可伸缩和与平台无关的三维图形合并到基于 Java 的应用程序和 applet 中。

IBM 正在进行几项非常有趣的有关图形和可视化方面的研究。

如果对 Java 3D 以外的图形编程领域感性趣,请访问 OpenGL 主页以获取有关这一健壮的库的信息。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值