大学的日子只剩下三个多月,仿佛又经历了一次轮回——开始留恋大学的生活。所以选择了留在学校做毕设,过完大学最后放纵充实的三个月。等毕业工作了,至少还能够对大学最后的日子有个自由的回忆。
毕设跟着以前实验室的老师,主要的内容是:对照片上的人物进行图像识别,然后映射到事先已建好的3D模型里面,实现对人物的检测。因为这个项目需要跟实验室现有的项目相契合,所以选用了Java3D来对3D模型进行操作。
附表
技术 |
实现层次 |
开发技术(难度) |
扩展性 |
最适合应用领域 |
Java3D |
中层(JVM) |
Java(较易) |
J2SE标准扩展(好) |
网上三维显示实现… |
OpenGL |
底层(显卡) |
C/C++(难) |
各大厂商支持(较好) |
三维设计软件… |
Direct3D |
底层(操作系统) |
C++(较难) |
Windows平台(差) |
三维游戏… |
VRML |
上层(网页) |
标记语言(容易) |
安装插件支持(一般) |
网上虚拟现实… |
Java3D API是用来开发三维图形和开发基于Web的3D应用程序(applet)的编程接口。目前用于开发三维图形软件的3D API(OpenGL、Direct3D)都是基于摄像机模型的思想,即通过调整摄像机的参数来控制场景中的显示对象,而Java3D则提出了一种新的基于视平台的视模型和输入设备模型的技术实现方案,即通过改变视平台的位置、方向来浏览整个虚拟场景。它不仅提供了建造和操作三维几何物体的高层构造函数,而且利用这些构造函数还可以建造复杂程度各异的虚拟场景,这些虚拟场景大到宇宙天体,小到微观粒子。
Java3D可实现的功能包括:
1). 生成简单或复杂的形体(也可以直接调用现有的三维形体)
2). 使形体具有颜色、透明效果、贴图。
3). 可以在三维环境中生成灯光、移动灯光。
4). 可以具有行为(Behavior)的处理判断能力(键盘、鼠标、定时等)
5). 可以生成雾、背景、声音等。
6).可以使形体变形、移动、生成三维动画。
7). 可以编写非常复杂的应用程序,用于各种领域如VR
1.1 JAVA3D简介:
Java3D API是Sun定义的用于实现3D显示的接口。3D技术是底层的显示技术,Java3D提供了基于Java的上层接口。Java3D把OpenGL和DirectX这些底层技术包装在Java接口中。这种全新的设计使3D技术变得不再繁琐并且可以加入到J2SE、J2EE的整套架构,这些特性保证了Java3D技术强大的扩展性。
1.2 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..
图一:在应用中的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:高分辨率坐标指定场景
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的渲染循环就开始工作。这样,场景就会和它的观察对象一起被绘制在画布上。
Java3D用有符号的、两位补码的256位定点数字来表示高分标率坐标。尽管Java3D保持内部高分辨率坐标表示的不透明,但用户用有八个整型变量的数组来表示256位的坐标。Java3D把数组中从索引号由0到7分别看作高分辨率坐标的从高到底位上的数。第128位上是二进制的小数点,也可以说在索引号为3和4的整数之间。高分辨率坐标的1.0就是1米。
假如是"小"的虚拟宇宙(类似于相对比例的几百米),在虚拟宇宙对象下的(0.0,0.0,0.0)点建立一个带有高分辨率坐标的Locale作为根节点就足够使用了;装入程序在装入过程中能自动构建结点,而在高分辨率坐标下的点不需要任何外部文件的直接描述。
大一些的虚拟宇宙期待被构建为有如同计算机文件那样的层次,这意味着一个根宇宙要包含由外部文件引用的嵌入虚拟宇宙。就这样,文件引用的对象(用户指定的Java3D组或高分辨率结点)定义了被读入现存虚拟宇宙的数据的位置。