`
梦中有你
  • 浏览: 60509 次
  • 性别: Icon_minigender_1
  • 来自: 天津
社区版块
存档分类
最新评论

用Java开发3D游戏之创建场景

 
阅读更多

本文将用一个Java 3D游戏来介绍Checkers3D以及如何使用它创建一个场景,该场景包含深绿色和蓝色间隔的平铺表面,其轴向是沿着x和z轴,一个蓝色的背景和一个浮动的可以从两个不同的方向照亮的球体。用户(观察者)能通过移动鼠标移动该场景。

  图1中左边的快照显示出程序起始的视图;右边的显示出用户移动一点后的场景图。


图1.起始和后来的视图


   Checkers3D游戏展示了Java 3D编程中许多共同之处及一些技巧。例如,3D场景的显示是使用Java 3D Canvas3D类完成的-这个类必须与Java的Swing组件集成到一起。所有的Java 3D应用程序要求一个场景图,而Checkers3D展示了怎样添加基本的形状、光源(环境光和有向光)和背景。该场景图用作文档的一种可视化形式,并且 借助于Daniel Selman的Java3dTree包可以容易地生成其信息的一种文本版本。

  地板和球利用了Java 3D的QuadArray、Text2D和球体几何体类。地板是在一个QuadArray中的一系列的四边形;而标签是利用Text2D对象沿着地板的主 轴放置的。球体的实现将向用户展示怎样着色,点亮和放置一个3D形状。用户从一种视图来观察该3D世界。你将看到如何在初始化过程中确定球体的位置,以及 如何在执行期间通过使用Java 3D的OrbitBehavior类来移动该球体的。

  一、 Checkers3D的类图

  图2中的类图显示该Checkers3D应用程序的所有的公共和私有数据及方法。


图2.Checkers3D的类图


   Checkers3D是该应用程序最顶层的JFrame。WrapCheckers3D是一拥有场景图的JPanel,该场景图可经由一 Canvas3D对象来观看。 CheckerFloor创建地板子图(如瓷砖,轴,等等),这里相同颜色的瓷砖是用一个ColoredTiles对象描述的。

  二、 集成Java 3D和Swing

  Checkers3D是一个JFrame-如果必要的话,可以把GUI控件,例如Swing文本域和按钮等放置到它上面。在本文的实例中,我创建了一个WrapCheckers3D(一个JPanel)的实例并把它放到一个BorderLayout的中央:

c.setLayout( new BorderLayout( ) );
WrapCheckers3D w3d = new WrapCheckers3D( );//3D画布的面板
c.add(w3d, BorderLayout.CENTER);


  在该场景上的Canvas3D视图是在WrapCheckers3D中创建的:

public WrapCheckers3D( ){
setLayout( new BorderLayout( ) );
//另外的初始化代码
GraphicsConfiguration config =SimpleUniverse.getPreferredConfiguration( );
Canvas3D canvas3D = new Canvas3D(config);
add("Center", canvas3D);
//另外的初始化代码
}


   当使用Canvas3D时必须小心,因为它是一个轻量级的GUI元素(在一个OS生成的窗口之上的薄层)。重量级的组件无法容易地与轻量级的Swing 控件相结合;这些控件大部分由Java生成。如果把Canvas3D对象嵌入到Jpanel中就可以避免这些问题;那么该面板就可以安全地与基于 Swing构建的应用程序的其它部分集成到一起。

  提示 在j3d.org(http://www.j3d.org/tutorials/quick_fix/swing.html)上有关于把Canvas3D和Swing相结合的详细讨论。

  与前面的章节中的应用程序相比,这里没有更新/绘制动画循环。这是不必要的,因为Java 3D包含它自己的机制来监视场景变化并且初始化着色。下面是该算法的伪码形式:

while(true){
处理用户输入;
if (存在请求) break;
执行行为;
if (场景图发生变化)
遍历场景图并着色;
}


  行为是一些场景图结点。它们包含能够影响图中其它部分的代码,例如移动形状或改变灯光。它们可以用于监控图形,从而把细节信息传递到应用程序中的非3D部分。

  有关细节可能要比这个伪代码中所建议的更为复杂,例如,Java 3D使用多线程来执行并行遍历和着色。然而,了解一下这个过程的大致思想将有助于你理解本文后面的代码。

 

 三、 创建场景图

  这个场景图是通过WrapCheckers3D的构造器创建的:

public WrapCheckers3D( ){
 //初始化代码
 GraphicsConfiguration config =SimpleUniverse.getPreferredConfiguration( );
 Canvas3D canvas3D = new Canvas3D(config);
 add("Center", canvas3D);
 canvas3D.setFocusable(true); //聚焦画布
 canvas3D.requestFocus( );
 su = new SimpleUniverse(canvas3D);
 createSceneGraph( );
 initUserPosition( ); //设置用户的观察点
 orbitControls(canvas3D); //控制移动观察点
 su.addBranchGraph( sceneBG );
}


   该Canvas3D对象被从getPreferredConfiguration()中得到的配置初始化;这个方法查询有关硬件的着色信息。一些老式的 Java 3D程序并不初始化一个GraphicsConfiguration对象,它们使用null作为到Canvas3D构造器的参数。这是一种不好的编程方 法。

  聚焦于canvas3D会使得键盘输入事件被发送到场景图中的行为中。行为经常是通过键的按下与释放来激活的,但是它们也可以由 定时器、帧变化和由Java 3D内部生成的事件来触发。在Checkers3D中不存在任何行为,所以没有必要聚焦。我把这相应的几行代码保留下来,因为它们在我们后面将要讨论的几 乎每种其它程序中都要使用。

  SimpleUniverse对象创建一标准视图分支图和场景图的VirtualUniverse及 Locale结点。createSceneGraph()方法设置灯光、天空背景、地板及浮动的球体;initUserPosition()和 orbitControls()负责处理观察者问题。在该方法的最后,结果BranchGroup被添加到该场景图上:

private void createSceneGraph( ){
 sceneBG = new BranchGroup();
 bounds = new BoundingSphere(new Point3d(0,0,0), BOUNDSIZE);
 lightScene( ); //添加灯
 addBackground( ); //添加天空
 sceneBG.addChild( new CheckerFloor( ).getBG( ) );//添加地板
 floatingSphere( ); //添加浮动的球体
 sceneBG.compile( ); //修改场景
} //createSceneGraph()结束


   各种方法把子图添加到sceneBG上以构建内容分支图。一旦该图被终结化并允许Java 3D对它进行优化,sceneBG就被编译。这种优化包含生成图、重分组和组合结点。例如,一串包含不同平移的TransformGroup结点可能组合 到单个的结点中。另一种可能是把所有的形状用相同的外观属性分组,这样它们可以更快地着色。

  边界是一个全局的BoundingSphere,用来指定对于灯光、背景和OrbitBehavior对象等环境结点的影响。边界球体放置在场景的中央并影响BOUNDSIZE个单位半径内的一切。边界盒和边界多面体在Java 3D中都是可用的。

  在WrapCheckers3D( )执行最后的场景图显示在图3中。

  其中的"Floor Branch"结点是我的发明,用来隐藏一些细节直到最后。图3中没有显示的是场景图的视图分支部分。

  四、 点亮场景

  一个环境灯光和两个有向灯光被通过lightScene()方法添加到该场景上。一个环境灯光可以达到世界中的每个角落并同等程度地照亮一切。

Color3f white = new Color3f(1.0f, 1.0f, 1.0f);
//设置环境灯光
AmbientLight ambientLightNode = new AmbientLight(white);
ambientLightNode.setInfluencingBounds(bounds);
sceneBG.addChild(ambientLightNode);


  这里环境光源是沿着边界创建的并且被添加到场景中。Color3f()函数中使用了红/绿/蓝色,范围为0.0f~1.0f。

  有向灯光模仿了具有一定距离的灯光的效果,从一个特定方向来照亮物体的表面。其与环境光的主要区别在于,它需要一个有关的矢量。

Vector3f light1Direction=new Vector3f(-1.0f,-1.0f,-1.0f);
//左面,下面,后面
DirectionalLight light1 = new DirectionalLight(white, light1Direction);
light1.setInfluencingBounds(bounds);
sceneBG.addChild(light1);

 


图3.Checkers3D中的部分场景图


  方向是连接点(0,0,0)和点(-1,-1,-1)的矢量;而灯光可以被想象成是方向与该矢量一致的多条平等线。

  点光源和斑点光源是其它形式的Java 3D光。点光源位置在空间上,其方向朝各个方向发出。斑点光源是聚集的点光源,它指向一个特定方向。

  一个场景的背景可以用一个固定的颜色(如下)、一静态的图像或一个纹理贴图几何体例如一个球体来指定:

Background back = new Background( );
back.setApplicationBounds( bounds );
back.setColor(0.17f, 0.65f, 0.92f); //天空颜色
sceneBG.addChild( back );

 

五、 浮动的球体

  球体是一个工具类,来自于Java 3D的com.sun.j3d.utils.geometry包,这是一个Primitive类的子类,而Primitive类是一个Group结点-它 有一个Shape3D子结点(见图3)。它的几何体在一个Java 3D TriangleStripArray中相邻-它指定球体是一个相连接的三角形的数据。我不必调整这个几何体,但是该球体的外观和位置确实需要改变。

  Appearance结点是一个包含大量参考信息-包括色彩、线、点、多边形、着色、透明度和材质属性-的容器。

  ColouringAttributes修正一个形状的颜色并且不受场景灯光的影响。对于一个要求颜色和光相交互的形状来说,需要使用Material组件。要使光影响一个形状的颜色,必须满足三个条件:

  ·该形状的几何体必须包括法线。

  ·该形状的Appearance结点必须有一个Material组件。

  ·该Material组件必须用setLightingEnable()启动了灯光效果。

  工具球体类能自动地创建法线,因此第一个条件很容易满足。

  六、 给球体加上颜色

  Java 3D Material组件控制一个形状当被不同的灯光点亮时展示什么颜色:

Material mat = new Material(ambientColor, emissiveColor,
diffuseColor, specularColor, shininess);


   ambientColor参数指定当被环境光点亮时形状的颜色:这使得对象具有一个统一的颜色。emissiveColor代表形状产生的颜色;这个参 数经常被置为黑色(等于off)。diffuseColor是对象点亮时的颜色,其亮度依赖于光柱与形状的表面形成的角度的大小。

  提示: 散射和环境颜色常被设置为相同色,这与真实世界中的大多数物体被颜色点亮时的方式相匹配。

  specularColor参数与形状与它的发光区的反射程度相关。这个值与亮度参数结合在一起。

  提示: 镜面光的颜色常被设置为白色,这与真实世界中的由大多数物体生成的镜面光的颜色相匹配。

  在Checkers3D中,有两个有向光源-它们在浮动球体的顶部创建两个闪亮的光环(见图1)。地板瓦还没有点亮,因为它们的颜色是用形状的几何体来设置的(见后面)。

  在floatingSphere()中管理球体的外观的代码如下:

Color3f black = new Color3f(0.0f, 0.0f, 0.0f);
Color3f blue = new Color3f(0.3f, 0.3f, 0.8f);
Color3f specular = new Color3f(0.9f, 0.9f, 0.9f); //近乎白色
Material blueMat= new Material(blue, black, blue, specular, 25.0f);
blueMat.setLightingEnable(true);
Appearance blueApp = new Appearance( );
blueApp.setMaterial(blueMat);


  七、 放置球体

   放置一个形状几乎总是一直通过把它的场景图结点放到一个TransformGroup(见图3中的球体Group)的下方来实现的。可以用一个 TransformGroup来放置、旋转和缩放放在它下面的结点,这里变换是用Java 3D Transform3D对象来定义的:

Transform3D t3d = new Transform3D();
t3d.set( new Vector3f(0,4,0)); //放在(0,4,0)
TransformGroup tg = new TransformGroup(t3d);
tg.addChild(new Sphere(2.0f, blueApp));
//设置球体的半径和外观
//并缺省地设置其法线
sceneBG.addChild(tg);


  这个set()方法把球体的中心放在(0,4,0)并且重置任何以前的旋转或缩放。set()可以用来在重置其它变换的同时实现缩放和旋转。方法setTranslation(),setScale()和setRotation()仅影响给定的变换。

  不象其它一些3D绘图包,Java 3D中的y轴在垂直方向上,而地面是由XZ平面定义的,如图4所示。

  在Checkers3D中球体的位置被设置为(0,4,0),这把它的中心放置到XZ平面上方4个单位的位置。


图4.在Java 3D中的轴向

原文:http://soft.yesky.com/468/2347968.shtml



分享到:
评论

相关推荐

    java3D游戏教程

    Java 3D游戏编程教程是面向想要学习如何利用Java技术创建三维游戏的开发者们的一份宝贵资源。这个教程可能包含了从基础知识到高级概念的全面讲解,帮助初学者和有一定经验的程序员掌握Java 3D API的使用,以及游戏...

    Java 3D 游戏开发

    总的来说,《Java 3D 游戏开发》是开发者掌握Java 3D技术并开发3D游戏的重要参考资料,它不仅讲解了理论知识,还提供了丰富的实践指导,对于想要在Java平台上构建3D游戏的程序员来说,是一本不可多得的宝典。

    Java2ME 3D游戏开发框架

    在使用OpenGL ES开发3D游戏前,需要理解几个关键概念: 1. **EGL(Embedded Graphics Library)**:是OpenGL ES与底层操作系统窗口系统的桥梁,提供平台无关的接口。EGL管理OpenGL ES的状态机,包括帧缓冲和渲染...

    java 3d游戏

    这个API为开发者提供了丰富的功能,包括对象建模、动画、光照、纹理映射等,使得Java成为开发3D游戏的强大工具。 Java 3D API是基于Java Foundation Classes (JFC)的,它扩展了Java AWT和Swing组件,使得3D图形可以...

    JavaME 3D游戏开发——基本图形渲染

    JavaME 3D游戏开发中的图形渲染技术,特别是对于基础图形如三角形的绘制,是构建复杂场景和游戏世界的基石。通过本文的解析,开发者可以深入理解OpenGL ES的使用方式,掌握关键的绘制流程。然而,这只是3D游戏开发中...

    java3D游戏编程源代码

    本项目提供的源代码可以帮助我们理解并学习如何在Java环境中创建具有类似CS(Counter-Strike)游戏体验的3D游戏。 首先,`JCmd.bat` 和 `cmd.bat` 可能是批处理脚本文件,用于自动化执行一系列命令行操作,例如设置...

    java 3D游戏

    随着计算机硬件性能的提升和玩家对游戏体验需求的增长,3D游戏已经成为游戏行业的主流,而Java以其跨平台、易学易用的特点,成为开发3D游戏的一个热门选择。 首先,我们要理解Java 3D API(Java 3D Application ...

    java3d游戏引擎

    Java3D游戏引擎是一款基于Java技术构建的强大游戏开发框架,专为创建三维图形和游戏而设计。这款引擎充分利用了Java语言的跨平台特性,使得开发者能够在多种操作系统上构建高质量的3D游戏,如Windows、Mac OS X和...

    java3D游戏模块代码

    总之,学习和理解这个Java3D游戏模块代码可以帮助我们掌握3D游戏开发的基本技术,包括对象建模、空间变换、视觉效果以及用户交互,这些都是开发3D游戏不可或缺的部分。通过深入研究和实践,我们可以创建出更生动、更...

    JAVA3D魔方游戏

    【JAVA3D魔方游戏】是一款使用Java 3D API开发的模拟魔方游戏,它为初学者提供了学习Java 3D编程的实践平台。Java 3D是Oracle公司提供的一个开源库,用于构建高性能、跨平台的三维图形应用程序。这款游戏通过Java 3D...

    JAVA_3D开发指导

    它提供了一个面向对象的API,使得开发者能够创建互动、动态的3D场景,广泛应用于游戏开发、虚拟现实、科学可视化等领域。本教程将深入探讨Java 3D的核心概念和技术,帮助你成为一名熟练的3D开发人员。 ### 一、Java...

    Java 3D 开发包

    Java 3D 开发包是Java平台上用于创建和呈现三维图形的应用编程接口(API)。它为程序员提供了丰富的功能,使得在Java应用程序中构建复杂的3D场景变得可能。这个开发包包含多个版本,如java3d-1_3-windows-i586-...

    java swing 游戏开发文档

    在Java Swing中进行3D游戏开发可以利用Java的丰富特性和Swing提供的组件来创建交互式的、视觉吸引人的游戏体验。本文档将深入探讨如何使用Java Swing进行3D游戏开发以及如何搭建3D开发环境。 首先,我们需要理解...

    3d小游戏+java开发

    【3D小游戏与Java开发】 Java作为一种广泛使用的编程语言,其在游戏开发领域的应用也日益凸显,特别是对于小型3D游戏来说,Java提供了强大的开发工具和技术支持。本篇将深入探讨如何利用Java进行3D小游戏的开发,...

    几个3D游戏开发的小例子

    在3D游戏开发的世界里,Java作为一种流行的编程语言,提供了许多工具和库来创建引人入胜的游戏体验。"几个3D游戏开发的小例子"这个压缩包文件包含了多个示例项目,旨在帮助初学者理解如何使用Java进行游戏开发。下面...

    java3d图形显示(JAVA开发 c/s架构)

    由于Java3D的1.5版本较为老旧,可能需要配合Java SE 5或6使用,对于现代Java开发环境(如Java 8及以上),开发者可能需要寻找替代方案,如JMonkeyEngine或者LWJGL等现代3D图形库。不过,理解Java3D的基本原理仍然对...

    java3d开发参考教程

    1. 场景图模型:Java 3D使用场景图(scene graph)的数据结构来表示三维场景。场景图是由节点构成的树状结构,每个节点代表了场景中的一个元素,比如几何体、光源、视点等。场景图提供了强大的数据组织能力,可以...

    java3D开发工具包

    开发3D应用时,Java3D提供了一些关键类,如`SceneGraphObject`作为所有3D对象的基类,`BranchGroup`用于组织场景中的多个对象,`TransformGroup`用于控制对象的位置和旋转,`Shape3D`用于表示基本几何形状,以及`...

    java3D开发包

    在实际开发中,Java3D可以应用于多种领域,如虚拟现实、科学可视化、游戏开发和教育软件。它简化了3D图形编程,使得具有Java背景的开发者无需深入学习OpenGL底层细节,也能创建引人入胜的3D应用。虽然现代的Java图形...

    薄荷引擎,基础Java的3D游戏引擎。创建方块沙盒游戏,创建渲染.zip

    薄荷引擎是一款基于Java开发的3D游戏引擎,特别适合初学者进行游戏开发,例如创建方块沙盒类游戏,如Minecraft风格的游戏。这款引擎提供了丰富的功能,可以帮助开发者快速构建游戏场景,实现3D物体的渲染和交互。在...

Global site tag (gtag.js) - Google Analytics