Java3D的场景图结构-程序员宅基地

技术标签: 虚拟机  网页游戏  JSP  EJB  JAVA 3D  数据结构  

 Java3D的场景图结构

  Java3D实际上是Java语言在三维图形领域的扩展,与Java一样,Java3D有纯粹的面向对象结构。Java3D的数据结构采用的是Scene Graphs Structure(场景图),就是一些具有方向性的不对称图形组成的树状结构(图1)。

  我们在一个Java3D应用程序看到的逼真三维场景从程序的角度看来,实际就是由Java3D定义的一系列的对象,这些对象不是杂乱无序,对象之间也不是毫无关系。如果想让三维图像正常显示,必须在这两点上遵循Java3D场景图的规定。观察图1,Java3D场景图的树结构由各种各样的对象组成:

  在图中出现的这些对象都实现了Java3D中有重要的意义的类,从逻辑上我们将它们分为三类:

  根节点(Root):Virtual Universe Object

  节点(Node):Local Object、Branch Group Nodes、Behavior Node、Shape3D Node…

  叶子节点(Leaf):Appearance、Geomery..

  图1:在应用中的Java3D场景图

  场景图中线和线的交汇点称为节点(Node),这些节点都是Java3D类的实例(Instance of Class),节点之间的线表示各个实例之间的关系。

  Virtual Universe是根节点,每一个场景图的Virtual Universe是唯一的。

  在Virtual Universe下面是Locale节点,每个程序可以有一个或多个Locale,但同时只能有一个Locale处于显示状态,就好象一个三维世界非常大,有很多个景点,但我们同时只能在一个景点进行观察。Java3D允许从一个Locale跳到另一个Locale,不过绝大多数程序只有一个Locale。

  每一个Locale可以拥有多个BranchGroup节点。所有三维形体的其位置信息(Transform Group Nodes)都建立在BranchGroup节点之上。

  TransformGroup Node用来设定Shape3D在Virtual Universe中的位置。

  Spape3D Node是三维图形节点,这个节点的实体放映在最后的显示画面中,就是三维世界中的每个形体。包括正方体、球体以及任何形状和外观的三维形体。

  位于场景图最下层的是两个叶子节点:三维体的外观(Appearance)和几何信息(Geometry),这两个节点定义了一个三维体的显示效果。

  View Platform位于图1的另一个分枝上,与前面所有描述三维体的性质的概念不同,View Platform和View都是用来定义观察者的信息。

  上面所列的概念很多,但是对于建立一个简单的Java3D程序,我们至少需要了解三个概念:虚拟宇宙(Virtual Universe)、场景(Locale)、坐标系统。

  2.1 虚拟宇宙(Virtual Universe)

  在Java3D中,虚拟宇宙被定义为结合一系列对象的三维空间。虚拟宇宙被用作最大的聚集体表现单位,同时也可被看作一个数据库。不管是在物理空间还是逻辑内容,虚拟宇宙都可以很大。实际上在大多数情况下,一个虚拟宇宙就可以满足一个应用程序所有的需求。

  虚拟宇宙是各自独立的个体,原因是在任何时候一个结点对象都不能在超过一个的虚拟宇宙中存在。同样的,在一个虚拟宇宙中的结点对象也不能在其他的虚拟宇宙中可见或者与其他的对象结合。

  对于一个Java3D应用程序,必须定义一个虚拟宇宙才可以在这个"宇宙"中显示三维图像。

  2.2 Java3D的坐标系统

  默认情况下,Java3D的坐标系统是右旋的,用方位语义学来解释就是:正y方向是本地重力的上,正x方向是水平的右,正z是这对着观察者的方向。默认的单位是米。

  双精度浮点、单精度浮点甚至是定点来表示的三维坐标都足够来表示和显示丰富的3D场景。不幸的是,场景不是真实世界,更不必说整个宇宙了。如果使用单精度坐标,有可能出现下列情景:

  离原点仅有一百公里的距离,被描绘得相当量子化,所能达到的最好效果就是三分之一英寸,在实际应用中这样的精度比要求的粗糙的多。

  如果要缩小到一个很小的尺寸(例如表现集成电路的大小),甚至在离原点很近的地方就会出现同坐标问题。

  为了支持一个大型的邻接虚拟宇宙,Java3D选择了有256位的高分辨率坐标:

  Java3D高分辨率坐标由三个256位的定点数组成,分别表示x、y、z。定点被固定在第128位,并且值1.0被定义为真实的1米。这个坐标系统足够用来描述一个超过几百万光年距离的宇宙,也可以定义小于一质子大小(小于一普朗克长度)的对象。

  在Java3D中,高分辨率坐标仅仅用于将更加传统的浮点坐标系统嵌入更高分辨率的底层系统。用这种方法,可以创造出一个具有任意大小和规模的在视觉上无缝的虚拟宇宙,而且可以不必担心数字上的精度。(参看表2)

  一个256位的定点数还具有能够直接表示几乎任何的合理适当的单精度浮点值。

  Java3D用有符号的、两位补码的256位定点数字来表示高分标率坐标。尽管Java3D保持内部高分辨率坐标表示的不透明,但用户用有八个整型变量的数组来表示256位的坐标。Java3D把数组中从索引号由0到7分别看作高分辨率坐标的从高到底位上的数。第128位上是二进制的小数点,也可以说在索引号为3和4的整数之间。高分辨率坐标的1.0就是1米。

  如果是"小"的虚拟宇宙(类似于相对比例的几百米),在虚拟宇宙对象下的(0.0,0.0,0.0)点建立一个带有高分辨率坐标的Locale作为根节点就足够使用了;装入程序在装入过程中能自动构建结点,而在高分辨率坐标下的点不需要任何外部文件的直接描述。

  大一些的虚拟宇宙期待被构建为有如同计算机文件那样的层次,这意味着一个根宇宙要包含由外部文件引用的嵌入虚拟宇宙。就这样,文件引用的对象(用户指定的Java3D组或高分辨率结点)定义了被读入现存虚拟宇宙的数据的位置。

  表2-1:Java 3D 高分辨率坐标

Java 3D 高分辨率坐标 2n Meters Units 87.29 Universe (20 billion light years) 69.68 Galaxy (100000 light years) 53.07 Light year 43.43 Solar system diameter 23.60 Earth diameter 10.65 Mile 9.97 Kilometer 0.00 Meter -19.93 Micron -33.22 Angstrom -115.57 Planck length

  2.3 场景(Locale)

  为了支持大型虚拟宇宙,Java3D提出了"Locale"的概念。Locale把高分辨率坐标作为起源。把高分辨率坐标看作精确的定位,它在高分辨率坐标的影响范围之内使用精度较低的浮点坐标指定对象的位置。

  一个Locale和与它结合的高分辨率坐标一起组成了在虚拟宇宙之下的一个表现层。所有虚拟宇宙包含一个或多个高分辨率Locale。而所有其他的对象都是附加在一个Locale上的。在整个体系中,高分辨率坐标扮演的是上层的仅供翻译的转换结点。例如,附加到一个特定Locale的所有对象的坐标都会与这个Locale位置的高分辨率坐标有关。(图2)

  图2:高分辨率坐标指定场景

  如果一个虚拟宇宙与传统的计算机图像的概念相近,给定的虚拟宇宙可能会变得太大。所以在通常情况下最好把一个场景图看作是一个高分辨率坐标场景的子结点。

  构造一个三维场景,程序员必须运行一个Java3D程序。这个Java3D应用程序必须首先创建一个虚拟宇宙对象并且至少把一个Locale对象附加之上。然后,构建出需要的场景图像,它由一个分支组结点开始并且包括至少一个观察平台对象,而场景图就是附加于这个观察平台。当一个包含场景图的观察对象被附加于一个虚拟宇宙,Java3D的渲染循环就开始工作。这样,场景就会和它的观察对象一起被绘制在画布上。

  2.4 编程实现一个三维世界

  这一部分描述怎样调用VirtualUniverse、Locale和HiResCoord对象的编程接口实现建立一个完整的"三维世界"。注意,这个三维世界有原点、坐标,是实现三维显示程序的第一步。

  VirtualUniverse对象有下列构造函数:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> 1 public VirtualUniverse()
2

  这个函数构造了一个新的VirtualUniverse对象,这个对象可以用来创建Locale对象。

  Locale对象有下列构建器:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> 1 public Locale(VirtualUniverse universe)
2 public Locale(VirtualUniverse universe, int x[], int y[], int   z[])
3 public Locale(VirtualUniverse universe, HiResCoord hiRes)
4

  这三个构建器在指定的VirtualUniverse中创建了一个新的高分辨率Locale对象。其中第一个形成了一个在(0.0,0.0,0.0)的Locale对象。其他的两个构建器在指定的坐标上建立了Locale对象。在第二种形式里,参数x,y,z是含八个32位整数的数组,这些数组指定了各自的高分辨率坐标。

  HiResCoord对象定义了一个使用三个高分辨率坐标的点,而每一个坐标又由三个定点数组成。每个高分辨率坐标数共有256位,第128位是二进制小数点。Java3D使用长度为八的整数数组来定义或提取一个256位的坐标值。Java3D用数组内的第一个整数来表示高32位,最后一个整数来表示低32位。

  HiResCoord 对象有以下的构建函数:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> 1 public HiResCoord( int x[], int y[], int z[])
2 public HiResCoord(HiResCoord hc)
3 public HiResCoord()
4

  第一个构造函数从输入的三个长度为八的整数数组生成高分辨率坐标。整数数组定义了与其同名坐标对象的值。第二个构造函数通过复制另外一个坐标创建一个新的坐标。第三个构造函数创建了一个值为(0.0,0.0,0.0)的坐标。

  所有Java3D程序都会首先建立VirtualUniverse和Locale对象,也就是说都会包含表3所示的代码。为了方便使用,Java3D为最原始的VirtualUniverse创建了几个子类:SimpleUniverse 、ConfiguredUniverse,这些子类保证了可以将三维图像轻易的在通过Canvas3D的对象在Applet或Frame中显示。其中最常用到的是SimpleUnivese对象,这个类位于包com.sun.j3d.utils.universe中。

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> 1 u = new SimpleUniverse(v,viewer);
2 u.getViewingPlatform();
3 ViewingPlatform viewingPlatform = u.getViewingPlatform();

 

Java3D引入了一种新的观察模式,这种模式使Java编写的显示效果符合"编写一次,随处运行"的原则。Java3D还把这种功能推广到显示设备或六等级自由度输入外部设备,例如跟踪摄像头。这种新的观察模式的"一次编写,随处观察"的特性意味着用Java3D观察模式编写的应用程序和Applet可以广泛应用于各种各样的显示设备。在不修改场景图的条件下,图像可以在包括标准电脑显示、多放射显示空间和安装摄像头设备的显示设备上被渲染。这也意味着在不需要修改场景图的情况下,同一个应用程序既能够渲染立体景象,还能通过摄像头的输入控制渲染过的观察图。

  Java3D的观察模式通过完全分离虚拟和现实世界来实现这种多功能性。这种模式区分了以下两种情况:

  一个应用程序通过控制观察平台的位置和方向在虚拟宇宙中对一个观察台对象(ViewPlatform)定位、定向和设定比例尺;

  渲染器使用已知位置和方向计算出要使用的观察对象,对终端用户物理环境的描述确定用户在物理环境中的位置和方向。

  3.1 为什么使用一个新的模式

  在底层的编程接口中可以找到基于照相机的观察模式,开发者通过它可以控制所有渲染图的参数。它可以应付处理常规的应用程序,但是处理有更广阔的适应性的系统的时候就显得力不从心,这些系统包括:把整个世界作为一个单元装入和显示的观察器或浏览器、可供终端用户观察、操纵、显示、甚至与虚拟世界交互的系统。

  基于照相机的观察模式仿效在虚拟世界中放置一个照相机而不是一个人。开发者必须持续重新配置一个照相机来模拟"在虚拟世界中有一个人"。

  Java3D观察模式直接和跟踪摄像头结合。在有摄像头的情况下,用户会有好像他们是真实的存在在那个虚拟世界的错觉,而开发者可以不做任何附加的工作就可以为用户带来这种效果。

  在没有摄像头并且只是用来表现一个单一的标准显示的情况下,Java3D观察模式表现得更像传统的基于照相机的观察模式,只是加上了能够产生立体透视图的功能。

  在一个需要由物理环境规定一些观察参数的系统中,让应用程序来控制所有的观察参数并不合理。

  例子就是:一个带有摄像头的显示设备可以用其光系统直接决定应用程序中的观察领域。不同的设备有不同的光系统,程序开发者硬绑定这样的参数或允许终端用户改变这样的参数都是不合理的。

  另外一个例子是:一个可以由用户当前的头部位置自动计算出观察参数的系统。只有一个对世界的说明和一条预先定义的轨迹可能不会严密的定义一个终端对象的观察。对于有摄像头设备用户,他们可能会期待在沿着一条固定的路线前进的时候能够看到他们左右两旁的物体。就好像在一个游乐场中,游客乘坐观光车按照固定的路线参观游乐场,但是在这过程中,游客可以持续转动他们的头。

  由于依靠终端用户的具体物理环境,观察的各个参数,尤其是观察和投影的基体变化很大。影响观察和投影基体的因素包括显示设备的物理尺寸,显示设备的安装方法(在用户的桌面或用户的头顶上),计算机是否知道用户的头在三维空间的位置,头顶装置真实的观察领域,显示设备上每平方英寸的像素数,还有其他类似的参数。

  Java3D建立的观察模式完全可以满足上述所有的需求。

  3.2 分离物理和虚拟

  Java3D分离了虚拟环境和物理环境:应用程序在虚拟环境中按照一定关系放置对象,而用户存在在物理环境之中,看计算机显示器并操纵输入设备。

  Java3D也定义了用户所在的物理世界和图像程序所在的虚拟世界之间最基本的通信。这种"物理到虚拟世界"的通信定义了一个单一的公共空间,在这个空间中用户的动作影响虚拟世界中的对象,而在虚拟世界中的任何活动都会影响最终用户的观察。

  虚拟世界是虚拟对象存在的通用空间。虚拟世界的坐标系统相对于每个Locale对象的高分辨率坐标存在,它定义了所有附加于这个Locale的虚拟世界坐标原点。包含当前活动的观察平台对象的Local定义了用来绘图的虚拟世界坐标。Java3D最后把所有图像单元的坐标转换到通用的虚拟世界空间中。

  物理世界就是指真实的世界。这是真实的用户存在和移动他(她)的头和手的空间。这也是使用任何物理追踪仪可以定义他们的局部坐标和几个标准的坐标系统被描述的空间。

  物理世界是一个空间,而不是Java3D不同的程序执行实例之间的通用坐标系统。所以当两个不同的计算机在世界上两个不同的地方同时运行同一个程序的时候,Java3D中没有直接来描述它们在物理世界坐标系统中相对位置的机制。因为标准问题,当地的跟踪系统仅仅定义了特定的Java3D应用程序实例的物理坐标系统。

  3.3 Java3D中用来定义观察的对象

  Java3D通过几个对象来发布它的观察模式。特别是View对象和与它相关的组件对象:PhysicalBody对象、PhysicalEnvironment对象、Canvas3D对象、Screen3D对象。图3描述了View对象的中心角色和组件对象的辅助角色。

  观察有关的对象都在图3中,它们起的作用如下:

  ViewPlatform(观察平台):一个view用一个叶子结点来在场景图为自己定位。观察平台的起始结点指定了它的位置、方向和在虚拟世界中的比例尺。

  View(观察):主要的观察对象包含了很多观察的状态。

  Canvas3D:抽象窗口工具箱中画布对象的3D版本。它描绘了一个可以让Java3D在上面画图像的窗口。它包括了一个对Screen3D对象的引用和描述一个Canvas3D要用到的尺寸、形状和位置信息。

  Screen3D:一个包含描述显示荧屏物理属性信息的对象。Java3D把显示荧屏信息分别放在单独的对象中,这样做可以防止在每一个Canvas3D对象中不同的显示屏幕信息共享一个屏幕。

  PhysicalBody:一个包含刻度信息的对象,它描述了用户的物理身体。

  PhysicalEnvironment:一个包含刻度信息的对象,它描述了物理世界。主要的信息描述了环境的六自由度硬件。

  图3:View和它的组件对象以及它们的相互联系

  这些对象一起描述观察的几何体胜于明白的提供观察或投影基体。Java3D的表现工具用这个信息来构造适合的观察和投影基体。这些观察对象的几何中心为产生一个观察提供了更大的弹性,这种弹性需要支持可以选择的显示配置。

  3.4 ViewPlatform: 在虚拟世界中的位置

  一个Viewplatform结点定义了一个坐标系统。这样,在虚拟世界中就有了一个有原点或参考点的参考系。观察平台是一个附加在观察对象的点并且作为决定描绘工具观察的基础。

  图4表示了一个场景图的一部分,它包括一个观察平台结点。直接在观察平台之上的结点决定了它在虚拟世界中的位置和方向。应用程序和或行为通过修改直接在观察平台之上任何与TransformGroup结点结合的Tramsform3D对象可以在虚拟世界中任意移动VierPlatform。一个简单的应用程序可能直接在一个观察平台上定义一个TransformGroup结点。

  一个虚拟宇宙可能有很多不同的观察平台,但是一个特定的View对象只能附加于一个单一的观察平台之上。这样,每个画在Canvas3D上的图画都是从一个单一的观察平台开始。

  图4:包含观察平台的一部分场景图

  3.5 如何在虚拟世界中移动

  应用程序通过修改观察平台的上级TransformGroup在虚拟世界中航行。修改一个观察平台的位置和方向的应用程序的例子包括:浏览器、提供航行控制的阅读器、做建筑预设计的程序、甚至是搜寻和毁坏游戏。

  控制观察平台对象能产生很有趣和有用的结果。我们可以定义一个简单的场景图,这个程序的目的是在窗口的正中画了一个对象并且绕自己的中心转动。

  我们不管在中心的对象,而让ViewPlatform在虚拟世界中绕圈。如果形体结点包括一个地球模型,这个程序可能产生一个类似于绕地球的远航员观察对象。

  如果在这个世界中加入更多的对象,这个场景图允许经由行为结点来浏览整个虚拟世界。

  图5:一个由观察控制的简单场景图

  应用程序和动作通过TransformGroup的可访问方法操纵它。这些方法允许应用程序得到和设置组结点的Transform3D对象。Transform3D结点有setTransform和getTransform两个方法。

  3.6 加载于喜欢的地方

  一个场景图可能包括多个观察平台对象。如果用户把一个观察对象从一个观察平台分离,然后把这个观察对象附加到另外一个不同的观察平台上。显示屏上的图像现在就要从新的观察平台上的观察点画图了。

  在Java3D的绘图机制中,真实的观察由当前附加观察平台的观察附加策略决定。观察平台定义了设置和得到观察附加策略的方法:

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> 1 public void setViewAttachPolicy( int policy)
2 public int getViewAttachPolicy()
3

  这些方法设置和得到在虚拟世界策略中的共存中心。默认的附加策略是View.NOMINAL_HEAD。观察平台的附加观察策略决定了Java3D怎样在观察平台中放置出射点。这个策略可以是以下的几个值之一:

  View.NOMINAL_HEAD:保证终端用户在物理世界名义上的眼睛位置对应于在虚拟世界中虚拟眼睛的位置。本质上,这个策略告诉Java3D要用同一种方法把虚拟出射点和观察平台原点及物理出射点和物理世界的原点相对放置。物理世界中出射点的方向和位置与原点的背离会产生相应的虚拟出射点的方向和位置在虚拟世界中的背离。

  View.NOMINAL_FEET:保证终端用户的虚拟世界中的脚一直接触虚拟地面,这个策略告诉Java3D要以这种约束计算物理-虚拟世界的通信。为达到之一目的,Java3D通过移动终端用户的眼睛位置和物理高度。Java3D用在PhysicalBody对象中的nominalEyeHeightFromGround参数来执行这个计算。

  View.NOMINAL_SCREEN:允许应用程序总是拥有一个和"感兴趣的点"保持"可观察"距离的出射点。这个策略也决定了Java3D计算"物理到虚拟世界"通信的方法。这个方法保证程序根据PhysicalBody对象定义nominalEyeOffsetFromNominalScreen参数来设置虚拟出射点与要表现的点之间的距离。

  3.7 在三维世界中建立、移动观察点

  形体移动的实现向来都是三维实现的难点和复杂之处,传统三维技术的实现多是注重模拟三维物体的真实移动。而Java3D除了提供传统的方案,还可以在一个存在的三维世界中移动一个观察点,借助观察点的移动模拟物体的移动。如同物理所学的切割磁力线发电,转子和静子本来就是一对可以互逆的对象,结果都是把动能转化为电能。例2的代码显示了在Virtual Universe中建立Viewer、ViewPlatForm、和如何通过绑定OrbitBehavior实现移动ViewPlatform。

  例2 建立、移动观察点代码

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> 1 setLayout( new BorderLayout());
2 Canvas3D c = new Canvas3D( null );
3 add( " Center " , c);
4 Viewer viewer = new Viewer(c);
5 Vector3d viewpoint = new Vector3d( 0.0 , 0.0 , 2.41 );
6 // 初始观察点位置        
7 Transform3D t = new Transform3D();  
8 t.set(viewpoint);        
9 ViewingPlatform v = new ViewingPlatform( );      
10 v.getViewPlatformTransform().setTransform(t);
11 u = new SimpleUniverse(v,viewer);        
12 u.getViewingPlatform();        
13 ViewingPlatform viewingPlatform = u.getViewingPlatform();
14 OrbitBehavior orbit = new OrbitBehavior(c, OrbitBehavior.REVERSE_ALL);      
15 BoundingSphere bounds =     
16 new BoundiBoundingSpherengSphere( new Point3d( 0.0 , 0.0 , 0.0 ), 100.0 );      
17 orbit.setSchedulingBounds(bounds);      
18 viewingPlatform.setViewPlatformBehavior(orbit);      
19 ….
20

Java3D可以很容易的与Java平台的其他技术相结合,如Applet、JSP、Serverlet、JDBC、EJB等。100%的纯Java实现是Java3D可以与如此多的Java平台技术结合的根本原因:

  同是Java平台保证Java3D可以在Applet中实现;

  Applet使Java3D可以轻易的在网页中显示;

  JSP、Serverlet技术保证将动态网页技术用于Java3D显示;

  Serverlet本身就是J2EE平台的核心技术,这使得Java3D可以搭建于J2EE平台。更可以使用所有J2EE的其他技术:JDBC、EJB、JMS…

  4.1 在网页上显示3D图形

  Java3D一个最大的特性是可以使用Applet作为显示容器,例3和例4的代码分别显示了如何在Applet中显示3D图形和在网页文件中(HTML)嵌入该Applet。

  例3 Applet实现Java3D

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> 1 Public class HelloUniverse extends Applet {
2 private SimpleUniverse u = null ;  
3 public BranchGroup createSceneGraph() {    
4 BranchGroup objRoot = new BranchGroup();    
5 ….    
6 return objRoot;  
7 }  
8 public void init() {
9 Canvas3D c = new Canvas3D(config);    
10 add( " Center " , c);  
11 ….
12 u.addBranchGraph(scene);  
13 }  
14 ….
15 }
16

  例4 在网页嵌入显示3D Applet

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> 1 < HTML >
2 < HEAD >
3 < TITLE > Hello, Universe !</ TITLE >
4 </ HEAD >
5 < BODY BGCOLOR = " #000000 " >
6 < applet align = middle code = " HelloUniverse.class " width = 256 height = 256 >
7 </ applet >
8 </ BODY >
9 </ HTML >
10

  4.2 动态网页技术与Java3D

  通过Jsp和Serverlet,可以使Java3D在网页中"动"起来。虽然Java3D本身就有三维动画的功能,但是这里的"动"指得是赋予了程序编写人员对Java3D动态的控制能力。改造上面的HelloUniverse,例5 的jsp代码可以实现控制旋转的正方体大小的功能。通过每次Random对象生成的随机数,立方体的大小也是随即改变,这段程执行的效果,如图6、7所示。

  例5实现可以动态调整三位物体大小的jsp代码

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> 1 <% @ page contentType = " text/html; charset=GBK " %>
2 < HTML >
3 < HEAD >
4 < TITLE > Hello, Universe !</ TITLE >
5 </ HEAD >
6 < BODY BGCOLOR = " #000000 " >
7 <% int i = 300 ; %>
8 <% float j = i * ( new java.util.Random()).nextFloat(); %>
9 < applet align = middle code = " HelloUniverse.class " width =<%= j %> height =<%= j %>>
10 </ applet >
11 </ BODY >
12 </ HTML >

  图6 Jsp显示效果1

 

         图6 Jsp显示效果2

        

  4.3 J2EE平台对Java3D的支持

  上面的例子只是通过动态设定Applet大小来控制Java3D的显示,实际上可应通过更多的方法实现Jsp、Serverlet对Java3D显示效果的控制,甚至可以将Java3D置于J2EE平台的显示层,实现对EJB、JDBC的调用。

  实现Java3D利用J2EE平台资源的方法很多,甚至可以直接在Java3D的实现类中直接调用EJB。但是从J2EE平台的设计模式出发,把对EJB调用放到Jsp中,而将返回的结果作为参数传入实现Java3D的Applet类中是一个更好的模式。具体代码见例6。

  例6调用EJB作为Java3D参数代码

<!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--> 1 <% @ page contentType = " text/html; charset=GBK " %>
2 <% @ page import = " javax.ejb.* " %>
3 <% @ page import = " java.rmi.* " %>
4 <% @ page import = " javax.rmi.PortableRemoteObject " %>
5 <% @ page import = " javax.naming.* " %>
6 <% @ page import = " java.util.Properties " %>
7 < HTML >
8 < HEAD >
9 < TITLE > Hello, Universe !</ TITLE >
10 </ HEAD >
11 < BODY BGCOLOR = " #000000 " >
12 <% try {  
13 Properties properties = null ;  
14 Context context = new InitialContext(properties);  
15 Object ref = context.lookup( " Customer " );  
16 EJBHome home = (EJBHome)PortableRemoteObject.narrow(ref,CustomerHome. class );  
17 CustomerHome home = (CustomerHome)home;    
18 Customer customer = home.findByPrimaryKey( " 1000000 " );  
19 String data = customer.getData();
20 }
21 catch (Exception e){e.printStackTrace();}
22 %>
23 < applet align = middle code = " HelloUniverse.class " width = 200 height = 200 >
24 < param name = " Data " value =<%= data %>>
25 </ applet >
26 </ BODY >
27 </ HTML >
28

  上面的代码首先访问JNDI名为"Customer"的EJB,然后将返回值作为参数传入实现Java3D的Applet。

  Java3D与J2EE是相互支持的关系:Java3D丰富、强化了J2EE的显示模式,使略显枯燥的J2EE客户端光鲜多彩;J2EE平台为Java3D提供了支持,功能强大的Server端处理能力为三维显示所需的复杂计算和大数据量提供了有力的支持。

  我们可以想象下面的两幅场景:

  通讯卫星将全国所有道路、建筑信息录入大型数据库;EJB实现应用逻辑并将之部署到AppServer上;所有支持JVM的手机、PDA、车载GPS可以通过调用EJB显示与真实世界一模一样的周围环境。

  地震局根据实际勘测到的地表等高线信息绘制二维矢量图,存为FDX文件;将二维图像转为三维实现的复杂算法放到EJB中实现;Jsp页面调用EJB后可以在Appet上实现三维GIS的显示。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/EKO_KL/article/details/83675775

智能推荐

Joomla源代码解析(二十二) 模块是如何被调用执行并渲染(下)_joomla module get params-程序员宅基地

文章浏览阅读1.7k次。上一文章中提到了getBuffer函数,在函数中实际上调用了render ,这个对象是JDocumentRendererModule 类的实例,我们看看JDocumentRendererModule 的render函数。if (!is_object($modu_joomla module get params

【转】EXPDP\IMPDP及EXP\IMP-程序员宅基地

文章浏览阅读55次。EXPDP\IMPDP及EXP\IMP2011年1月6日数据泵文件expdp介绍EXPDP命令行选项1. ATTACH该选项用于在客户会话与已存在导出作用之间建立关联.语法如下ATTACH=[schema_name.]job_..._sql imp 转储文件和日志文件不可相同

logging模块-程序员宅基地

文章浏览阅读171次。logging模块是Python内置的标准模块,主要用于输出运行日志,可以设置输出日志的等级、日志保存路径、日志文件回滚等;相比print,具备如下优点:多线程支持可以通过设置不同的日志等级,在release版本中只输出重要信息,而不必显示大量的调试信息;print将所有信息都输出到标准输出中,严重影响开发者从标准输出中查看其它数据;logging则可以由开发者决定将信息输出到什么..._logging中可以选择很多消息级别

Android Gson中的Map与JSON相互切换_android map转json string-程序员宅基地

文章浏览阅读2.9k次。源: { "mapBean": { "mapBean-key1": { "id": "1", "name": "cyy1" }, "mapBean-key2": { "id": "2", _android map转json string

Flask返回页面及Json数据_flask同时返回文件和json-程序员宅基地

文章浏览阅读1.4k次。Flshk返回Html页面及Json数据#!/usr/bin/python# -*- coding: utf-8 -*-import jsonfrom flask import Flaskfrom flask import requestfrom flask import redirectfrom flask import jsonifyfrom flask import rend..._flask同时返回文件和json

F-One在汽车行业如何善用“数据”做营销与财务?_f-one怎么用-程序员宅基地

文章浏览阅读1.5k次。​10月25日,刚过完1024程序猿节,又迎来一场热闹的中国汽车CIO峰会(ACS2017)。在上海星河湾酒店,来自海内外的一百多家汽车整车及零部件制造商、经销商、以及汽车信息化解决方案供应商汇聚于此。本次峰会以“互联网+时代的汽车全产业链信息化解决方案”为主题,讨论汽车业界发展动向以及如何借助信息化技术实行汽车产业链的优化升级。一站式商业分_f-one怎么用

随便推点

深入Linux内核网络堆栈_linux 内核network stack主要功能。-程序员宅基地

文章浏览阅读1.9k次。作者:bioforge [email protected] 原名: >翻译,修改: duanjigang [email protected]>翻译参考:raodan (raod_at_30san.com) 2003-08-22 第一章 简介本文将描述如何利用Linux网络堆栈的窍门(不一定都是漏洞)来达到一些目的,或者是恶意的,或者是出于其它意图的。文中会就后门通讯对Netfilter钩_linux 内核network stack主要功能。

C语言实现弹跳小球_c语言弹跳小球代码-程序员宅基地

文章浏览阅读1.1w次,点赞11次,收藏44次。简单的控制台弹跳小球#include &lt;stdio.h&gt;#include &lt;stdlib.h&gt;#include &lt;conio.h&gt;#include &lt;windows.h&gt;// 全局变量 int x,y; //小球坐标 int velocity_x,velocity_y ; //速度 int left,right,top,bottom; /..._c语言弹跳小球代码

主动轮廓模型——Snake分割算法(MATLAB)_基于因子分解的主动轮廓模型-程序员宅基地

文章浏览阅读2.7k次,点赞2次,收藏19次。学习图像分割算法,在网上找到的关于主动轮廓模型的实现代码,自己简化总结了一下,在这里和大家分享,欢迎提问snake是一种能量最小的曲线,表示为v(s) = (x(s), y(s)), s为归一化的曲线长度,s∈[0, 1]。能量函数由曲线内部能量和外部约束力(图像力)组成, 表示为Esnake= ∫Esnake(v(s))ds =∫..._基于因子分解的主动轮廓模型

STM32MP1如何让洗衣机操作界面更炫酷?_海尔stm操作图片-程序员宅基地

文章浏览阅读480次。随着经济以及时代的快速发展,人们对家里的生活电器需求不断增长,很多家用电器的传统按键以及旋钮操作已经无法满足人们对多功能的要求,越来越多的家电采用触摸屏的控制形式,米尔针对该应用场景基于STM32MP1打造了HMI2.0人机交互界面,让传统洗衣机更加智能炫酷。米尔提供的洗衣机HMI界面是STM32MP1开发应用的一个参考,此外还有更多各类智能家用电器的应用场景,相对于传统家电的人机交互设计更加炫酷和人性化,搭配米尔专业的嵌入式Linux软硬件开发的经验,能够让家用电器产品更加智能化。本文将展示米_海尔stm操作图片

2.3 二进制乘法运算(定点原码一位乘)_原码一位乘法右移补什么-程序员宅基地

文章浏览阅读913次,点赞4次,收藏5次。2.3.1 原码一位乘步骤:①对给定的x*y,其中x为被乘数,y为乘数;②计算过程中取双符号位(避免加法时产生假溢出),初始时部分积为0,将乘数的数值部分的绝对值写到乘数部分。 ③判断乘数的最低位:如果为1,则执行部分积=部分积+x,且右移一位;如果为0,则执行部分积=部分积+0,且右移一位。④移位的次数=乘数的数值位的位数。 ⑤计算符号位,组合数值部分的值即为结果。 原说法有点抽象,我..._原码一位乘法右移补什么

python爬取百度天气接口【实战记录】_百度天气爬取-程序员宅基地

文章浏览阅读2.2k次,点赞5次,收藏9次。文章目录前言一、确定爬取的对象二、开始分析前言利用python 模拟浏览器获取百度的天气接口提示:以下是本篇文章正文内容,下面案例可供参考一、确定爬取的对象http://weathernew.pae.baidu.com/weathernew/pc?query=%E6%9D%AD%E5%B7%9E%E5%A4%A9%E6%B0%94&srcid=4982&city_name=%E6%9D%AD%E5%B7%9E&province_name=%E6%B5%99%E6%_百度天气爬取