可用于虚拟建筑环境的Web3D技术初探-3
2.8 关于采用VRML建立虚拟建筑环境的几点说明
RML对于虚拟场景的描述能力主要是通过VRML提供的各种类型节点提供的,本文非VRML技术介绍,一些对于虚拟环境重要的节点如纹理贴图,声音等在本文相关工作中被涉及但未提及.
提高VRML的交互性能的一个重要的方法就是在Script节点中引用Java代码,另一种方法是采用EAI的方法.这两种方法不仅依赖于浏览器对Java的支持,还依赖于VRML插件(Plug-in),这些插件对Java的支持并不完全.这种方法实际上是实现了浏览器插件提供的接口,其实现的功能必然受到浏览器插件本身的制约.
尽管VRML已经取得了广泛的应用,但也存在其局限性.目前浏览VRML的场景,用户需要下载安装相应的插件,使用户感到不便.另外,VRML仅仅是一种用于描述基于互联网的虚拟三维场景的规范,其提供的交互性对于开发复杂的应用稍嫌不足,另外,场景描述信息与交互信息共存在同一VRML文件中不便开发者使用.
2.9 本章小结
1.VRML是在Internet上建立三维虚拟世界的描述工具,VRML定义了三维应用系统中常用的语言描述以及一些简单的行为特征的描述功能.
2.VRML可用于在Internet上建立虚拟的建筑环境,根据虚拟建筑环境相关特点,在建立虚拟建筑场景应用过程中,应采取相应对策,如采用LOD优化场景.
3.利用VRML的交互性能可以模拟虚拟建筑中的行为特征以提高场景的真实性与趣味性,但VRML采用脚本来实现有限的交互性不能满足虚拟建筑环境中复杂的交互功能.
4.VRML的不足之处在于VRML仅仅是一种描述性的标记语言,对于开发复杂的交互式三维应用采用VRML很难实现.另外,浏览VRML的场景,用户需要下载安装相应的插件,使用户感到不便.
本章参考文献:
[1]International ISO/IEC 14772-1:1997[DB-OL]. http://www.web3d.org/technicalinfo /specifications/vrml97/index.htm.
[2]The Virtual Reality Modeling Language Concepts[DB-OL]. http://www.vrml.org/ Specifications/ VRML97/part1/concepts.html.
[3]ISO/IEC 10646-1:1993 Information technology-Universal Multiple-Octet Coded Character Set (UCS)-Part 1: Architecture and Basic Multilingual Plane, Internet standards track protocol[OL]. http://www.iso.ch/isob/switch-engine-cate.pl searchtype=refnumber&KEYWORDS=10646.
[4]陈彦云.高度复杂场景真实感绘制技术的研究[D]. 中国科学院软件研究所.2000,54-56.
[5]潘志庚.马小虎.石教英.虚拟现实中多细节层次模型自动生成技术综述[J].中国图象图形学报,1998,(4):754—759.
[6]张茂军. 虚拟现实系统[M]. 北京:科学出版社.2001,189-190.
本章注释:
①本章VRML的介绍部份参考了ISO/IEC Standard 14772-1:1997规范.关于VRML97的ISO/IEC规范,可参见International ISO/IEC 14772-1:1997:
http://www.web3d.org/technicalinfo/specifications/vrml97/index.htm.
②utf8,Universal Multiple-Octet Coded Character Set.参见ISO/IEC 10646-1:1993 Information technology. http://www.iso.ch/isob/switch-engin-cate.pl searchtype= refnumber &KEYWORDS =10646.
第三章 Java3D及其在开发基于Web的三维系统中的应用分析
Java3D是适用于网络环境的跨平台的三维图形开发工具包,是Java 2 JDK的标准扩展[1].Java最大的特点在于它的平台无关性,在Windows 95/98,Windows NT,Solars,Unix等平台上,都使用相同的代码,Java实现了"Write once, Run anywhere".Java的平台无关性使其特别适合于互联网环境下编写应用程序.
3.1 Java3D的特性及与VRML的比较
Java3D是Java 2 JDK的标准扩展的一组API(Application Programming Interface),Java3D对底层的图形库OpenGL和DirectX进行了封装,从而保证了高效的执行效率.
Java属于面向对象的语言,Java3D封装了大量的类,编写Java3D程序时,大多情况下只需找到所需的类加以应用.相对于OpenGL和DirectX,Java3D更容易掌握,编程效率更高.
Java3D的优点还在于它的代码的可传输性,和其它Java程序一样,利用Java3D可以编写Application程序和Applet程序,用来生成三维场景的Applet可以方便的从服务器传送到客户端,然后在客户端运行.
相对于VRML,VRML只是一种描述语言,只能支持简单的脚本控制场景与用户的交互行为.Java3D则是Java语言在三维应用的扩展,Java3D的功能和可编程性更强,Java3D有丰富的Java类库的支持,实现各种编程行为,这是VRML难以达到的.
3.2 Java3D运行环境
Java3D根据硬件平台的配置,可以选用DirectX和OpenGL不同的版本,Java3D封装了不同的底层的图形库,然而不同的底层采用相同的接口,从而为采用Java3D编写应用程序提供了极大的方便.运行Java3D需要安装Java3D运行环境.在Windows平台可下载Java3D for Windows(OpenGL Version) Runtime for Java①.
运行Java3D,需要指定JRE运行路径,在Path加入"%JAVAHOME%\bin",还要确定在CLASSPATH中已指定j3daudio.jar,j3dcore.jar,j3dutils.jar和vecmath.jar四个文件的位置,这四个文件是J
ava3D的基本类库;也可拷贝文件到JRE的扩展库目录"%JAVAHOME%\jre\lib\ext\"中.
3.3 Java3D场景图的结构
Java3D采用基于场景图(Scene Graph)的编程模型.Java3D提供了大量Java3D类,开发者可以通过实例化这些类创建各种Java3D对象.这些对象包括几何体,外观(Geometry),灯光(Light),变换(Transform),声音(Sound)以及行为(Behavior)等.
Java3D程序生成的三维场景由一系列的Java3D对象组成,它们以类似VRML的DAG图(Directed-acylic Graph)的结构形式组成整个三维场景, Java3D各节点以DAG图的结构形式组织起来称为场景图(SceneGraph),而三维场景的绘制就是对SceneGraph各个节点的遍历绘制.
图是由节点(Node)和弧(Arc)组成的数据结构.节点表示数据元素,而弧表示数据之间的关系.在Java3D的场景图中,场景图中的节点是Java3D类的实例,弧则表示不同Java3D实例之间的关系.
Java3D实例之间的关系主要有两种,一种是父子关系,另一种为引用关系.
场景图可作为设计Java3D的工具或文档,场景图使用图3-2图中所示图例表示.实际的Java3D一般拥有比场景图描述的更多的对象.
Java3D的场景图中,最底层的节点是Virtual Universe, Virtual Universe对象定义了一个虚拟的三维空间.
Virtual Universe对象维持了一系列Locale对象的列表,一个Locale对象可以理解为一个原始的坐标系,这个坐标系中的所有对象,也就是这个Locale对象的子节点,其相对位置都是相对于该Locale对象的引用点(局部坐标系的原点).
每一个Java 3D程序可以有一个或多个Locale节点,但同一个时刻只能有一个Locale 节点处于激活状态.一个BranchGroup对象是一个子场景图(Subgraph)的根节点.有两类不同的子场景图:内容子图和视图(View)子图.内容子图包含虚拟场景的内容对象,如几何特性,外观,行为,位置,声音,光源等.视野子图包含虚拟场景中ViewPlatform 对象,ViewPlatform节点定义了观察者(Viewer)的位置,方向等.
View对象包含了从一个观察点以某种观察模式渲染三维场景的所有参数.所有被View对象包含或引用的对象将被渲染到一个被View对象引用的3D画布(canvas3D)上.Screen3D对象则包含了一个具体的Screen参数,用于将渲染结果映射到具体的显示设备上.一个简单的Java3D场景图如图3-3.
3.4 创建Java3D程序
创建一个Java3D程序大致如下几步:
(1)创建一个Canvas3D对象.
(2)创建一个VirtualUniverse对象.
(3)创建一个Locale对象,将Locale对象关联到VirtualUniverse对象.
(4)创建View子图.
a.创建一个ViewPlatform对象.
b.创建一个PhysicalBody对象.
c.创建一个PhysicalEnvironment对象.
d.创建一个View对象,将ViewPlatform,PhysicalBody,PhysicalEnvironment和Canvas3D对象关联到View对象上.
(5)构造内容子图.
(6)编译子图
(7)将子图插入到Locale节点.
Java3D提供了一个SimpleUniverse类,该类实现了(2)-(4),可以大大的简化代码有利于使开发者将工作集中在创建场景内容上.
场景的内容一般包括几何形体,外观,光照,声音,行为等对象,它们按Java3D场景图的规则组成内容子图.
Ex4-1:
//导入使用的Java类
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.event.*;
import java.awt.GraphicsConfiguration;
//导入Java3D类
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.geometry.ColorCube;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class HelloUniverse extends Applet {
private SimpleUniverse u = null;
public BranchGroup createSceneGraph() {
// BranchGroup根节点
BranchGroup objRoot = new BranchGroup();
TransformGroup objTrans = new TransformGroup();
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
objRoot.addChild(objTrans);
// Shape3D 节点
objTrans.addChild(new ColorCube(0.4));
// 优化场景图.
objRoot.compile();
return objRoot;
}
//构造方法
public HelloUniverse() {
}
public void init() {
setLayout(new BorderLayout());
GraphicsConfiguration config =
SimpleUniverse.getPreferredConfiguration();
Canvas3D c = new Canvas3D(config);
add("Center", c);
// 创建场景并添加到SimpleUniverse中
BranchGroup scene = createSceneGraph();
u = new SimpleUniverse(c);
// 移动观察平台使得场景内容可以被观察者观察到
u.getViewingPlatform().setNominalViewingTransform()
u.addBranchGraph(scene);
}
public void destroy() {
u.removeAllLocales();
}
// 以下代码允许程序在可以以Applet小程序方式运行的同时也可以以应用程序方式运行
public static void main(String[] args) {
new MainFrame(new HelloUniverse(), 256, 256)
;
}
}
3.5 创建形体
3.5.1 基本几何形体
Java3D的核心类中并未提供基本的形体类,因而在程序中无法直接生成经常使用的一些基本形体.在Java3D的工具包中提供了一些基本形体如Box,Cone,Cylinder等,这些类包含在com.sun.j3d.utils.geometry包中.
3.5.2 Geometry形体
在3D计算机图形中,从最简单的三角面片到复杂的三维场景模型都是由基于顶点的数据来建模和渲染的.三维图形从某种角度上就是点,线,面组合生成的各种基本形体,在由基本形体组合成各种复杂形体.
Java3D中,Geometry类是一个抽象父类,包括各类点,线,面等都是Geometry的子类.Geometry的子类有三种,无索引的基于顶点的几何体,有索引的基于顶点的几何体以及Raster,Text3D,CompressedGeometry等可视对象.其中无索引的基于顶点的几何体在渲染的时候每个顶点只被渲染一次,有索引的基于顶点的几何体在渲染时可能被渲染多次.
图3-5是Geometry类及其子类的继承关系:
在Java3D中,每个Shape3D对象通过调用setGeometry()方法来引用Geometry对象.关于Geometry及其子类的具体应用,这里不在赘述.
Geometry形体提供了采用程序的方法构造数据集从而创建几何形体的方法具有重要的应用意义,如数据的可视化.
3.6 在Java3D中调用VRML场景
复杂的三维形体一般很难直接通过编程实现,虚拟建筑环境中的场景对象包含大量复杂的场景对象,如建筑物,雕塑,树木等,这些三维形体大多由CAD软件生成,并且在工程设计过程中已经大量存在各种类型的CAD图形文件,应充分利用这些资源.
Java3D可以调用其它格式的三维图形文件来获得复杂形体,如VRML2.0格式,OBJ格式的三维文件.Java3D也可以间接的调用DWG,DXF,3DS,DGN格式的三维文件,一些常用的三维图形软件都提供了不同文件类型的转换程序,如Discreet的3DS MAX就可以读入DWG,DXF,3DS格式的文件,并把它们转换成VRML2.0的格式.
常用的流行的三维图形软件有:
Autodesk公司的AutoCAD[3]
Bentley公司的MicroStation[4]
SGI公司的Alias/WaveFront/Maya[5]
Discreet的3DS MAX[6]
Java3D的com.sun.j3d.loaders包中包括了Loader和Scene两个接口,在Java3D中调用不同格式的3D图形文件,应根据这两个接口编写自己的Loader类,针对不同类型的3D图形文件编写不同的Loader类,因为采用相同的接口,对类的使用者来说针对不同类型文件的Loader调用的方法基本是相同的[7].
SUN提供了一个VRML97的Loader[8],可以利用它来在Java3D中调用VRML97类型的文件.使用它首先下载一个JAR文件,VRML97.jar.使用VRML97.jar设置好其路径.通常VRML97.jar应放在%JAVAHOME%\lib目录中.
以下是一个VRMLLoad类,它将一个指定URL的VRML文件转换为Java3D的场景类型,VRMLLoad类的getInstance()方法将返回一个TransformGroup对象,里面包含了VRML文件的描述的场景内容.
Ex4-2:
import javax.media.j3d.*;
import java.io.*;
import com.sun.j3d.loaders.vrml97.VrmlLoader;
import com.sun.j3d.loaders.Scene;
public class vrmlLoad {
//Vrml文件的url
private java.net.URL filename;
private TransformGroup tg;
public vrmlLoad(java.net.URL url) {
filename = url;
tg = new TransformGroup( );
VrmlLoader loader = new VrmlLoader();
Scene s = null;
try{
s = loader.load(filename);
}catch (Exception e){
System.err.println(e);
System.exit(1);
}//End try
tg.addChild(s.getSceneGroup( ) );
}
public TransformGroup getTS(){
return tg;
}
}//end of vrmlLoad.java
VrmlLoader实现了com.sun.j3d.loaders包中Loader接口.该接口主要的接口方法如下:
Scene load(java.io.Reader reader): 从reader导入场景,并返回一个包含场景数据的Scene对象.
Scene load(java.lang.String fileName): 从fileName指定的文件导入场景,并返回一个包含场景数据的Scene对象.
Scene load(java.net.URL url): 从url指定的网络资源位置导入场景,并返回一个包含场景数据的Scene对象.
void setFlags(int Flags): 设置导入文件的标志,该标志决定导入场景文件时对不同类型的场景对象的选择策略.标志取值及意义如下:
Flags的取值
取值意义
LOAD_ALL
LOAD_BACKGROUND_NODES
LOAD_BEHAVIOR_NODES
LOAD_FOG_NODES
LOAD_LIGHT_NODES
LOAD_SOUND_NODES
LOAD_VIEW_GROUPS
…
允许导入场景中所有节点对象
允许导入场景中背景对象
允许导入场景中行为对象
允许导入场景中雾对象
允许导入场景中光照对象
允许导入场景中声音对象
允许导入场景中视图对象
…
3.7 与用户交互
交互性能对于三维虚拟环境来说是至关重要的,Java3D的交互式应用主要有三类.第一类是利用Java的事件处理模型,第二类是利用Java3D提供的Behavior包中提供的utility对象,第三类是定义自己的Behavior对象.
3.7.1 采用Java的事件模型
Java的事件处理采用的是一种"事件派遣模型",在应用中,首先向事
件源注册监听器,若事件源处发出了一个事件,针对已就那个事件向事件源注册了的所有监听器对象,事件源就会向它们全体发出一个通知.监听器对象属于一个类的实例,该类实现了监听器接口.监听器对象必须实现相应的监听器接口方法,实现对事件的处理.
具体作法如下:
用implements说明该类实现的监听器接口,
public class className extends Applet implements WindowListenter,
ActionListerer,
ItemListener{}
注册监听器,如一个菜单条作为事件源,
Menu m=new Menu(String s);
m.addActionListener(this);
实现监听器接口的方法
Public void actionPerformed (ActionEvent e){
…//do something
}
其中actionPerformed()方法实现了监听器接口,针对事件作出相应的处理.
3.7.2 行为(Behavior)对象的分析
Behavior类是Java3D中定义的一个抽象类,它定义了所有Behavior对象的公共属性.Behavior类的运行机制在于Behavior对象可以接收特定的激励(stimuli),如键盘按键,鼠标移动等,然后对这一激励作出响应,如改变观察者的视点,虚拟物体的位置,外观等.分析Behavior类有助于编写自己的针对特殊要求的行为类.
Behavior类的主要方法有:
initialize()
posted(int posted)
processStimimulus(java.util.Enumeration criteria)
setEnable(Boolean state)
setSchedulingBounds(Bounds region)
wakeupOn(WakeCondition criteria)
…
Initialize方法允许一个Behavior对象初始化其内部状态和指定唤醒条件.当一个Behavior对象所包含的BranchGroup对象在场景中被创建的时候,Behavior对象的initilize()方法被调用.Java3D并未为initilize()方法分配新的线程,因此,initilize()必须正常返回以便使Java3D重新获得程序的控制权.
在initilize()方法中还应指定一个唤醒条件,否则processStimulus方法不会被执行.
processStimulus()方法接收并处理Behavior的激励信息.Java3D只有在该Behavior处于激活状态且该Behavior的所有唤醒条件被满足的时候才调用该方法.
wakeupOn()方法用于在WakeCondition 指定的唤醒条件成立时被唤醒,从而形成激励.其中WakeCondition是所有实现唤醒功能类的基类.其子类定义了许多复杂的唤醒条件,如响应AWT事件,响应物体之间的碰撞,响应指定的时间经过等.
构造Behavior对象引用它所控制的对象,这样,对该引用的改变才会反映到它原来的对象上.
所以,创建一个Behavior对象则需:
(1)编写一个构造函数,在该函数中保存控制对象的引用.
(2)重载initilize()方法,指定第一次唤醒条件.
(3)重载processStimulus方法,根据不同的唤醒条件触发不同的动作,重新设置唤醒条件.
以下实现了一个重定义的Behavior类,该Behavior类通过键盘控制一个TransformGroup沿一用户定义的坐标轴旋转.
Ex4-3:
import javax.media.j3d.*;
import javax.vecmath.*;
import java.awt.event.*;
import java.util.Enumeration;
public class MyBehavior extends Behavior{
//定义MyBehavior控制的TransformGroup对象
private TransformGroup targetTG;
private Transform3D rotation = new Transform3D();
private double angle = 0.0;
// MyBehavior 构造方法
public MyBehavior(TransformGroup targetTG){
this.targetTG = targetTG;
}//End Constructor MyBehaviorApp()
public void initialize(){
// 设置初始的唤醒条件
this.wakeupOn(new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED));
}//End initialize()
public void processStimulus(Enumeration criteria){
// do …
angle += 0.1;
rotation.rotY(angle);
targetTG.setTransform(rotation);
//重新设置初始的唤醒条件
this.wakeupOn(new WakeupOnAWTEvent(KeyEvent.KEY_PRESSED));
}//End processStimulus()
}//End MyBehavior
在程序中使用myRotationBehavior类,
TransformGroup objRotate = new TransformGroup();
//设置objRotate可写属性
objRotate.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
MyBehavior myRotationBehavior = new MyBehavior(objRotate);
//设置myRotationBehavior作用范围
myRotationBehavior.setSchedulingBounds(new BoundingSphere());
objRoot.addChild(myRotationBehavior);
其中wakeupOn()指定了激励条件为WakeupOnAWTEvent (KeyEvent.KEY_PRESSED),另外processStimulus()方法的最后应重新设置唤醒条件.
3.8 Java3D在建立虚拟建筑环境应用中的几点说明
Java3D API提供了丰富的可用于建立虚拟建筑环境应用的类,如灯光,雾,纹理,声音等,一些类本文应用但未提及.
Java3D是Java 2 JDK的标准扩展,Java3D可以和Java 2D,Swing,AWT,JMF[9]②,JDBC[10]③等很好的结合,实现如图像处理,文字显示,绘制二维图形,交互式用户界面等.图3-5是作者采用Java3D结合JMF编写的一个虚拟电视机模型,程序将一影音文件作为纹理映射到一个三维表面对象上,说明了Java3D与JMF共同工作的能力
.
相对于VRML,Java是一门相对复杂的编程语言,正是基于此,Java3D具有更大的灵活性,例如将科学数据(如数字高程模型数据,洪水淹模型)转化为三维可视化的效果都可以通过Java3D实现,这对于VRML是难于实现的.
另外,JDK工具以及Java3D,JDBC,JMF等包是SUN公司免费的开发工具,通过Java3D建立的虚拟建筑环境应用不会涉及一般商业及授权问题,具有更大的长期效益.
3.9 本章小结
本章讨论了Java3D技术的基本特性及应用,着重说明了Java3D在虚拟建筑环境应用中其技术上的突出之处.
本章给出了将VRML文件导入Java3D场景的方法和应用.
本章讨论了如何实现在Java3D虚拟环境中与用户交互的方法.
本章参考文献:
[1]Java3D[OL]. http://java.sun.com/products/java-media/3D.
[2]Dennis J Bouvier . Getting Started with the Java 3D API[OL]. http://java.sun.com/ products/java-media/3D/collateral/
[3]Autocad[OL]. http://www.Autodesk.com/.
[4]MicroStation[OL]. http://www.bentley.com.
[5]Maya[OL]. http://www.aliaswavefront.com.
[6]The 3D Studio Max[OL]. http://www.discreet.com.
[7]File Loader Archives[OL]. http://www.j3d.org/utilities/loaders.html.
[8]VRML97 Loader[OL]. http://java.sun.com/products/java-media/3D/ download.html.
[9]JMF API[OL]. http://www.javasoft.com/products/jmf/.
[10]JDBC API[OL]. http://www.javasoft.com/products/jdbc/.
本章注释:
①Java3D for Windows(OpenGL Version) Runtime for Java下载地址http://java.sun.com/products/java-media/3D/index.html.
② Java Media Framework, JMF, Java媒体框架,用于Java多媒体编程的一组API.
③ Java DataBase Connectivity,JDBC,Java数据库连接,是Java企业版的一部分,提供了Java程序跨平台,跨数据库的数据访问能力.
第四章 基于Java3D和VRML的虚拟建筑环境
VRML97是目前在Internet上建立虚拟三维场景所采用的最为广泛的工具,其本身已成为国际标准,从而保证了VRML的稳定性.另外,许多CAD软件都带有VRML格式文件的输出工具,如Bentley的MicroStation ,Discreet Inc.的3D Studio Max,Silicon Graphics Inc.的CosmoCreate[1]等,使用这些软件可以确保快速的建立基于VRML的三维场景.
三维场景的再现,在三维场景中采用不同的交互方式进行漫游是虚拟建筑环境的基本要求,这部分可以采用Java3D来实现.在此基础上,采用Java可以实现其它更为复杂的功能.
本章解决以下几个与虚拟建筑环境相关的问题:
1.在Java3D中获取VRML的节点.
2.在三维场景中漫游.
3.在三维图形环境下实现建筑物属性信息查询.
4.1 在Java3D中获取VRML节点
4.1.1 VRML与Java3D的综合应用
基于Web的虚拟建筑应用中采用VRML作为虚拟场景的描述工具,而采用Java3D编写应用程序.要实现对场景中对象的操作,需要把VRML描述的节点对象转换为Java3D对象,然后将它们按Java3D场景图的结构组织起来,然后按普通的Java3D程序逐次添加其它功能.图4-1说明了同时采用VRML与Java3D的应用模型.
图4-1中一个VRML文件被解析并转换成一系列Java3D的Shape3D节点对象(实际应用中不仅只有Shape3D对象),然后被加到同一个TransformGroup组中,图中还定义了一系列继承了Behavior类的用户代码来对一系列Shape3D对象或TransformGroup对象进行操作.
4.1.2在Java3D中获取VRML节点
当使用Loader将一个VRML文件导入Java3D中,Loader接口的Load的方法将返回一个com.sun.j3d.loaders.Scene对象,一般情况下可以调用Scene的getSceneGroup()方法,该方法将返回一个BranchGroup对象,该BranchGroup对象可以被Java3D的场景图直接引用.
在虚拟建筑环境的应用中,经常需要获得单个类型场景对象实例,因为许多行为和操作都是针对单个场景对象,比如场景中有若干栋建筑,需要在Java3D程序的运行时刻将它的外观(表面纹理)改变,来观察其在环境中不同的效果.如果在一个VRML文件中定义了若干栋建筑,那么将其导入到Java3D中,必须做的事情之一就是获得每栋建筑物的单个实例,以便将它们作为单独的对象进行处理.
Shape3D对象维持了对一系列Geometry对象的引用.Shape3D对象除了定义了三维形体的几何特征,还定义了形体的外观(Appearance)属性.
一个VRML的Shape对象被导入到Java3D场景中将被转换为Java3D的Shape3D对象,这样就动态的访问该对象.
Ex4_01
DEF BUILDING_01 Shape
{
appearance Appearance
{…
}
}
geometry IndexedFaceSet
{
coord Coordinate
{
point
[ …
]
}
texCoord TextureCoordinate
{
point
[…
]
}
colorPerVertex FALSE
convex FALSE
coordIndex
[ …
]
solid FALSE
texCoordIndex
[…
]
}
}
Ex4_01定义了一个VRML的Shape对象,并用DEF语句将其命名为"BUILDING_01".BU
ILDING_01的Geometry域IndexedFaceSet类型,它可以用来定义复杂的几何形体.包含这个Shape节点的VRML文件假设其文件名为XXX_Scene.wrl.
首先将VRML文件导入到Java3D场景中.
url= java.net.URL(path + "XXX_Scene.wrl");
VrmlScene scene = vrmlLoader.load(url);
其中path是XXX_Scene.wrl所在位置的路径.
Scene接口的getNamedObject()方法返回一个Hashtable对象,该对象将VRML命名过的节点存储在一个DEF表中,在调用get()方法时通过指定节点的名字将该节点对象提取出来,并将其造型(Casting)为Shape3D类型.
Hashtable defTable = scene.getNamedObjects();
Shape3D building_01 = (Shape3D) defTable.get("BUILDING_01");
Building_01为Shape3D类型的对象,它对应于VRML场景中的"BUILDING_01"节点.
如果在Java3D中对一个Shape3D对象实现各种类型的操作,需要指定Shape3D的Capability属性.
Shape3D的Capability属性标志如下:
标志
标志的意义
ALLOW_APPEARANCE_READ
ALLOW_APPEARANCE_WRITE
ALLOW_COLLISION_BOUNDS_READ
ALLOW_COLLISION_BOUNDS_WRITE
ALLOW_GEOMETRY_READ
ALLOW_GEOMETRY_WRITE
…
程序运行时允许读入外观
程序运行时允许写入外观
程序运行时允许读取碰撞包围范围
程序运行时写入写入碰撞包围范围
程序运行时允许读入几何体
程序运行时允许写入几何体
…
例如要改变一个Shape3D的外观属性,那么首先要做的是将外观属性设为可写.
shape3D.setCapability(ALLOW_APPEARANCE_WRITE);
然后就可以对Shape3D对象的Appearance对象进行操作了.在程序运行中还可以动态的删除或添加Shape3D节点,从而可以实现模型替换的功能.
4.2 在虚拟建筑环境中漫游
虚拟建筑环境的一个重要功能就是在虚拟建筑环境中漫游.漫游可以简单的理解为在虚拟场景中不断的根据用户的输入而动态的调整观察点位置,观察方向,视角等参数,调整过程中场景被不断的渲染从而形成连续的观察者画面,使浏览者产生在虚拟的场景中游览的效果.
观察点及目标点的运动模式的不同反映的直接效果是不同的漫游模式,如Walk,Fly,Examine等.
在虚拟场景中,视点处于虚拟的场景中,观察效果类似视点对虚拟场景中的物体发出的投射光线在一个图像板上的投影效果,Java3D提供了丰富的View相关的类,使开发者不必过多涉及复杂的投影变换等问题.
上一页123456