![]() |
摘要: 借助EAI 和Script 节点Java 和VRML 相结?构徏了一个三l交互式的虚拟场?该场景克服了VRML 在交互方面的不,实现了用户与虚拟场景之间以及(qing)用户与用户之间的交互和共享的功能,q在此基?构徏了一个用于计机囑Ş学教学的虚拟场景框架,为VRML 在远E教育方面的普及(qing)和应用做了有益的探烦. 关键? VRML ;Java ; EAI ; 交互?虚拟场景 虚拟现实技术是当前国际上的一个研I热?是一U逼真的通过各种传感讑֤模拟人在自然环境中的视、听、动作等行ؓ(f)的h机界面技?实现操作者和环境直接q行自然交互. 该技术已l广泛地应用于军事、航I天、医学、徏{设计、机械、地理、化学等众多的领? 虚拟现实建模语言(Virtual Reality Modeling Language , ~写为VRML) 是一个开攄、可扩充的三l场景描q语a,它描qC如何在World Wide Web 上创建和览三维虚拟场景. VRML 的构思始?994 q春瑞士日内瓦的万维|?WWW) 的第一届国际会(x)议上. 1994 q?0 月在芝加哥召开的第二次万维|会(x)议上公布了VRML1. 0 的规范草?其主要的功能是生成静态的3D 场景,以及(qing)与HTML 链接的一些功能和措施. 1998 q? 月VRML 被I(xin)SO 正式批准为国际标? ISO/ IEC/ 4772 -1 :1997 , 通常被称为VRML1997 , 也被UCؓ(f)VRML2. 0) . VRML2. 0 版将VRML 的静态世界改变ؓ(f)动态世?q强化了互动功能,此外q增加了动画、传感器、事件、行为和脚本{功? VRML 提供?4 个功能强大的节点用于描述三维场景中的对象,能够利用层次性文件关pdZQ意大的动态境界[ 1 ]. 目前,国内在虚拟现实技术的应用斚w除了个别领域?基本上还处于探烦研究阶段,主要是应用VRML 的三l徏模功能创Z个用户可以浏览的静态三l场?而在创徏动态场景和多用户场景方面的研究相对较少. 本文旨在讨论使用VRML 与J ava 创徏多用户交互式场景的结合方?q给Zpȝ框架和实现方?
1 VRML 与J ava 相结?/strong>
VRML 场景中Q何用DEF 定义的节炚w可以被J ava Applet E序所讉K,获得一个节点的句柄?该节点的event In 和eventOut p被引? Java Applet 可以监视VRML 场景中节点的改变q能够在节点间传递事件来直接改变节点的属? 单的?一斚wEA I 能把VRML模型的变化传递给J ava Applet , 另一斚wJava Applet 可以通过EA I lVRML 传送各U各L(fng)事g和信?控制和改变虚拟场? browser = Browser. getBrowser() ;
2. 3 多用户共享的实现
|
q?br />
现在Q移动游戏和Ud应用开发极为热门!游戏中需要有旉漂亮的图形,其设计标准比以前M时候都要高。本文将告诉你怎样用酷毙的Ud3D囑ŞAPI为J2ME讑֤开?D囑Ş游戏?br />
如果你在用MIDP1.0q行用户接口~程Q那么有两条路你可以选择Q用高U的UIcL者一切由你自׃头开始。作为游戏开发者,W一U选择往往是不可能的;q是Z么游戏开发者不得不Z们的高游戏开发自q3D引擎的原因。无疑,q需要付出大量的旉和努力,而缺乏QҎ(gu)支持的CLDC 1.0QMIDP 1.0正是Z其上Q对问题的解x有多大帮助?br />
在MIDP 2.0中,有一个可选的叫移?D囑ŞAPI的Y件包Q或者叫JSR 184。该API是第一个基于Java标准开发的Ud讑֤上的三维囑Ş软g包。该API既有高又有低囑Ş特征Q其中,高特征UCؓ(f)保留模式Q低U特征称为立x式。保留模式得开发者有可能使用场景囑Şq场景中的物体Ҏ(gu)虚拟相机和灯光的位置q行自n的着艌Ӏ立x式能够允许应用程序直接进行物体绘制。如果需要,可以在同一个应用程序中使用q两U模式。本文着重介l立x式?br />
3D API
让我们以列D和解释该3D API中的cM为开始。除了这些API外,JSR 184q包含了一个场景图形结构和一个相应的文g格式以有效地理和配|?D内容。该文g格式定义了一Um3g文gQ这U文件典型地?D建模文g应用E序中{换而来?/p>
?Q?D APIc?/p>
c? | 描述 |
AnimationController | 控制动画序?/td> |
AnimationTrack | 把一个KeyframeSequence同一个AnimationController相关联?/td> |
Appearance | 定义一个网|MeshQ或一个Spring3D的着色属性的一l对象?/td> |
Background | 定义视图是怎样被清除的?/td> |
Camera | 一个场景图点Q它定义了场景中观察者的位置以及(qing)?D?D的投影?/td> |
CompositingMode | 一个Appearancec,它封装了每一个像素的合成属性?/td> |
Fog | 一个Appearancec,它包含了雑的有兛_性?/td> |
Graphics3D | 一个单独的3D囑Ş上下文。所有的着色操作都是在该类中的render()Ҏ(gu)中实现的?/td> |
Group | 一个场景图形结点,它存储了一个无序的l点集作为它的子l点?/td> |
Image2D | 一个二l图像,可用于纹理,背景Q或者精灵图像?/td> |
IndexBuffer | 该类定义了如何把点q接h以Ş成一个几何体?/td> |
KeyframeSequence | 装了一pd的具有时间戳和矢量值的关键帧的动画数据?/td> |
Light | 描述了不同类型的光源?/td> |
Loader | 下蝲和反串行化图形结点及(qing)l点成分Q以?qing)整个场景图形?/td> |
Material | 装了进行光学计的材质属性? |
Mesh | 描述了一?D对象Q它是用多边形面定义的?/td> |
MorphingMesh | 描述了一个顶点-变Ş的多边Ş|眼?/td> |
Node | 所有场景图形结点的抽象基类。其五个具体子类是:(x)CameraQMeshQSprite3DQLight和Group?/td> |
Object3D | 所有可以成?D世界中组成部分的对象的抽象基cR?/td> |
PolygonMode | 装了多边ŞU别属性?/td> |
RayIntersection | 存储了对于分割的Mesh或Sprite3D的引用,以及(qing)有关分割点的信息?/td> |
SkinnedMesh | 描述了一个框架动ȝ多边形网眹{?/td> |
Sprite3D | ?D位置来描qC?D囑փ?/td> |
Texture2D | 装了一?DU理囑փ和一个属性集合,q些属性指囑փ是如何应用到子网g的?/td> |
Transform | 一个通用?x4的QҎ(gu)矩阵Q用来描qC个变换?/td> |
Transformable | Node和Texture2Dcȝ抽象基类?/td> |
TriangleStripArray | 定义了一个三角Ş带数l?/td> |
VertexArray | 一个整型矢量数l,描述了顶点位|,法线Q颜色或者纹理坐标?/td> |
VertexBuffer | 存储对于VertexArrays的引用,它包含了一个顶炚w的位|,颜色Q法U,以及(qing)U理坐标?/td> |
World | 一个特别的Groupl点Q它作ؓ(f)场景图最层的容器?/td> |
举例
我们开发一个简单的旋{一个多边Ş?D应用E序Z。该多边形是一个立方体Q它的纹理是一张旧汽R相片。列?展示了例Emidlet的主要类-应用E序的中心类。该c负责创建应用程序ƈ建立赯行MyCanvas的计时器?/p>
列表1. MIDletMainc?/p>
import javax.microedition.midlet.*; import javax.microedition.lcdui.*; import java.util.*; public class MIDletMain extends MIDlet { static MIDletMain midlet; MyCanvas d = new MyCanvas(); Timer iTimer = new Timer(); public MIDletMain() { this.midlet = this; } public void startApp() { Display.getDisplay(this).setCurrent(d); iTimer.schedule( new MyTimerTask(), 0, 40 ); } public void pauseApp() {} public void destroyApp(boolean unconditional) {} public static void quitApp() { midlet.destroyApp(true); midlet.notifyDestroyed(); midlet = null; } class MyTimerTask extends TimerTask { public void run() { if( d != null ) { d.repaint(); } } } } |
列表2昄了MyCanvasc,该类包含了应用程序的所有图形逻辑。init()Ҏ(gu)负责l点的创建,U理文g的装载ƈ讄U理Q外观和背景也被一赯|。paint()Ҏ(gu)负责着色ƈ旋{立方体。图1展示了正在一个模拟器中运行的实际E序?
列表2. MyCanvasc?br />
import javax.microedition.lcdui.*; import javax.microedition.m3g.*; public class MyCanvas extends Canvas { private Graphics3D graphics3d; private Camera camera; private Light light; private float angle = 0.0f; private Transform transform = new Transform(); private Background background = new Background(); private VertexBuffer vbuffer; private IndexBuffer indexbuffer; private Appearance appearance; private Material material = new Material(); private Image image; public MyCanvas() { // 创徏Displayable对象以探听命令事?br /> setCommandListener(new CommandListener() { public void commandAction(Command c, Displayable d) { if (c.getCommandType() == Command.EXIT) { MIDletMain.quitApp();}} }); try { init();} catch(Exception e) { e.printStackTrace();} } /** * lg的初始化 */ private void init() throws Exception { addCommand(new Command("Exit", Command.EXIT, 1)); graphics3d = Graphics3D.getInstance(); camera = new Camera(); camera.setPerspective( 60.0f,(float)getWidth()/ (float)getHeight(), 1.0f, 1000.0f ); light = new Light(); light.setColor(0xffffff); light.setIntensity(1.25f); short[] vert = { 5, 5, 5, -5, 5, 5, 5,-5, 5, -5,-5, 5, -5, 5,-5, 5, 5,-5, -5,-5,-5, 5,-5,-5, -5, 5, 5, -5, 5,-5, -5,-5, 5, -5,-5,-5, 5, 5,-5, 5, 5, 5, 5,-5,-5, 5,-5, 5, 5, 5,-5, -5, 5,-5, 5, 5, 5, -5, 5, 5, 5,-5, 5, -5,-5, 5, 5,-5,-5, -5,-5,-5 }; VertexArray vertArray = new VertexArray(vert.length / 3, 3, 2); vertArray.set(0, vert.length/3, vert); //立方体的各个l点法线 byte[] norm = { 0, 0, 127, 0, 0, 127, 0, 0, 127, 0, 0, 127, 0, 0,-127, 0, 0,-127, 0, 0,-127, 0, 0,-127, -127, 0, 0, -127, 0, 0, -127, 0, 0, -127, 0, 0, 127, 0, 0, 127, 0, 0, 127, 0, 0, 127, 0, 0, 0, 127, 0, 0, 127, 0, 0, 127, 0, 0, 127, 0, 0,-127, 0, 0,-127, 0, 0,-127, 0, 0,-127, 0 }; VertexArray normArray = new VertexArray(norm.length / 3, 3, 1); normArray.set(0, norm.length/3, norm); //各个l点的纹理坐?br /> short[] tex = { 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1 }; VertexArray texArray = new VertexArray(tex.length / 2, 2, 2); texArray.set(0, tex.length/2, tex); int[] stripLen = { 4, 4, 4, 4, 4, 4 }; // 对象的VertexBuffer VertexBuffer vb = vbuffer = new VertexBuffer(); vb.setPositions(vertArray, 1.0f, null); vb.setNormals(normArray); vb.setTexCoords(0, texArray, 1.0f, null); indexbuffer = new TriangleStripArray( 0, stripLen ); //U理囑փ image = Image.createImage( "/pic1.png" ); Image2D image2D = new Image2D( Image2D.RGB, image ); Texture2D texture = new Texture2D( image2D ); texture.setFiltering(Texture2D.FILTER_NEAREST, Texture2D.FILTER_NEAREST); texture.setWrapping(Texture2D.WRAP_CLAMP,Texture2D.WRAP_CLAMP); texture.setBlending(Texture2D.FUNC_MODULATE); // 创徏外观QAppearanceQ对?br /> appearance = new Appearance(); appearance.setTexture(0, texture); appearance.setMaterial(material); material.setColor(Material.DIFFUSE, 0xFFFFFFFF); material.setColor(Material.SPECULAR, 0xFFFFFFFF); material.setShininess(100.0f); background.setColor(0xffffcc); } protected void paint(Graphics g) { graphics3d.bindTarget(g, true, Graphics3D.DITHER | Graphics3D.TRUE_COLOR); graphics3d.clear(background); //讄照相?br /> Transform transform = new Transform(); transform.postTranslate(0.0f, 0.0f, 30.0f); graphics3d.setCamera(camera, transform); //讄灯光 graphics3d.resetLights(); graphics3d.addLight(light, transform); //讄旋{ angle += 1.0f; transform.setIdentity(); transform.postRotate(angle, 1.0f, 1.0f, 1.0f); graphics3d.render(vbuffer, indexbuffer, appearance, transform); graphics3d.releaseTarget(); } } |
? 正在一个模拟器中运行的应用E序
结
JSR 184对于可以q行MIDP 2.0的设备来_(d)是一个节省时间和I间的可选的软g开发包。它允许开发者用两U图形方?保留模式和立x?来?D囑Ş。本文集中讲qC立即模式Qƈl出一个例子程序来说明怎样使用3D API?br />