查看: 1719|回复: 1
打印 上一主题 下一主题

[经验分享] 软件设计与实现--基于java3d的虚拟漫游

[复制链接]

2508

主题

2

听众

3万

积分

资深设计师

Rank: 7Rank: 7Rank: 7

纳金币
32806
精华
12

最佳新人 活跃会员 热心会员 灌水之王 突出贡献

跳转到指定楼层
楼主
发表于 2012-6-1 09:38:26 |只看该作者 |倒序浏览
1.Java3d 简介
Java 3D API 的设计是对以前流行的诸如 OpenGL 和 Direct3D 的 3D 图形 API 的重大革新(以前的 API 是同 3D 硬件设计紧密结合的低级过程性 API)。Java 3D 是一种功能强大的、面向对象的 API,它提供了许多超出我们认为作为“3D 图形 API”所能有的功能。Java 程序员可能会发现 Java 3D 编程环境非常熟悉而且易用。Java 3D 做了许多事情来为您管理图形数据,这样就使得您可以把精力集中在其它编程工作上。
使用 Java 3D,首先要在场景图中设置所有的图形对象(也称为几何对象),场景图是一个层次模型,它包含有关场景中的对象以及如何渲染它们的全部信息。然后,将该场景图交由 Java 3D 渲染。您无须为显示数据而编写任何代码 ― Java 3D 为您完成了这项工作。通过使用内置的强大工具,您可以在一个更高的级别上进行编程。

1.1场景图树
Java 3D 场景图是一棵由两个部分或分支组成的树,这两个部分是:内容(content)和视图(view)。视图分支含有复杂 Java 3D 视图模型的所有细节,它还定义视点。好的事情是,对于大多数简单的应用我们都可以使用统一实用类(尤其是“正如其名称所暗示”的 SimpleUniverse 类)来处理视图管理的大多数复杂任务。
内容分支描述了您将在场景中看到什么 。它包含所有图形对象(球体、立方体或更复杂的几何对象)、用来移动它们的转换、光、行为、组节点和烟雾。我们的大多数工作将集中在内容分支。

1.2组节点
Group 对象组成了场景图内容分支的内部节点 。您可以使用 Group 节点来将您的场景图组织成相互关联的部分。每个 Group 节点包含一些子节点,在处理该节点时将渲染这些子节点。Switch 节点和 TransformGroup 节点是特殊的 Group 节点,它允许您对场景图施加进一步的控制。TransformGroup 节点在处理期间对它们的子节点应用 3D 变换(诸如平移、缩放或旋转),这使得您可以移动、旋转或缩放整个场景图。 Switch 节点限制在渲染期间访问哪些子节点,使您可以控制渲染场景图的哪些部分。以 Quake 为例,您可以将所有不同的武器分组到一个 Switch 节点下面,使得您可以只渲染当前使用的武器。

1.3能力位(Capability bits)
Java 3D 将会通过尽可能地预先计算值来优化场景图的渲染。如果想在渲染场景时更改场景的某些方面,则必须使用能力位来指定以后想更改的数据。例如,使一个对象动起来需要更改影响该对象的变换。为了做到这一点,需要在 TransformGroup 中启用 ALLOW_TRANSFORM_WRITE 位

2.大赛题目分析

2.1创建模型库:
将场景中所需模型如沙发,电视机,等具体的模型,并不采用更细的模型来搭配场景。

2.2三维场景交互功能:
只是在场景中添加大点的模型,比如在房间中添加桌子,电视等,对模型进行变换操作

2.3情感交流功能我们是没有思路实现。

2.4场景漫游功能:
可以通过方向键进行场景全方位漫游,如前进,后退,上升,下降,左右旋转。并实现碰撞检测。  

3.我的实现思路
无论是实现程序与模型分离还是实现点取还是碰撞检测,我们都离不开一个对象shape3d它是我的实现思路的核心所在。
Shape3d是什么啊?说简单点,就是我们场景中一个一个模型,它可以是一个桌子,一个椅子,也可以是一个房子,我说他是我们整个场景也一点也不为过,我这么说应该能说明shape3d的作用了吧。

3.1导入模型到场景中
获得所有的shape3d对象,将其添加到一个集合中。而我们每次添加程序时,都会去遍历这个存储了shape3d对象的集合。可能有人会说,shape3d对象是添加在BranchGroup结点上的,而java3d对象规定一个子结点是不允许有两个父结点的,这样的理解是错的。在集合里我们只是存储了一个shape3d对象的引用而以,再说了集合也不是结点哦。

3.2动态添加模型到场景中
程序启动时添加的模型叫静态添加,而在场景中运行时,我们要想在场景中添加模型必须有相应的能力被设置了才有效,所以要动态添加模型必须设置父结点的可扩展能力位。

3.3动态模型的删除。
同添加一样,为了移除结点,必须首先设置父结点允许子结点分离。

3.4最主要的是模型的更新功能
模型的更新功能包括:模型的纹理修改,模型点取能力设置,模型的碰撞能力设置。
模型纹理修改:前面我已说过,我们场景中的所有模型都是shape3d,而shape3d又可以设置其纹理,这样的话实现修改纹理就比较方便了。我们通过 swing菜单生成需要的外观对外(应该能理解吧,就是通过菜单获取所需图片,以及相应的贴图坐标,贴图模型,边界模型等)然后通过shape3d的setAppearce()更改其外属性。

3.5模型点取能力设置:
虽然我们可以通过上面的方法去实现纹理修改,但一定是存在问题的,比如说,在集合中那么多的shape3d对象,如何能得到自己所要修改的那个对象呢??
这个问题开始我们也想了好长时间,后来我们找到的解决方案是通过点取,点取我们所需要的对象。
在JAVA3D我们找到了一个好的行为点,是这个类让我想到了方法,这个类就是PickrotateBehavior, PickZoomBehavior, PickTranslateBehavior
该类实现的特别好,误差不是很大,对一些规则物体的点取几乎没误差,它是根据规则体的6个顶点坐标取值,所设置的碰撞检测范围,也许其它采用java3d开发的团队也发现了这个类,但这个类是点取时是不会返回对应的shape3d对象的。所以这个时候我们也特别失望,但我们没有放弃。我们发现PickMouseBehavior对象的updateScene()方法,可以获取一个shape3d对象。

   
        
            
            PickScene = new PickObject(canvas, root)   //canvas是画布,root是一个父结点,
                                        shape3d=(Shape3d)pickScene.pickNode(pickScene.pickClosest(xpos, ypos, PickObject.USE_BOUNDS), PickObject.PRIMITIVE);
            //这样就获得了shape3d对象
            
        
   


3.6模型的碰撞能力设置
通过以上说明,碰撞检测就好实现了。。我们在遍历模型时,将每个shape3d对象的范围获得,然后用此范围生成一个判断视野进入的碰撞检测范围,用此范围生成一个WakeupOnViewPlatformEntry类的对象(new WakeupOnViewPlatformEntry(bounds));这样的话,当我们的视野进行此范围时,就会被检测到,由WakeupOnViewPlatformEntry的processStimulus()方法进行处理, 我们采用碰撞后,让前进的位移变为 0 。当左右旋转时,位移恢复。

4.总结。
整个大赛结束时,我感到有些遗憾,因为我们的作品和大赛的完整程序有很大差距,暑期快结束时,我才意识到我们需要从引擎的角度进行考虑。我们得有一个类似引擎处理方式的思路。开学后大赛虽然还留了时间,可是这时候我们已没时间去完成大赛了,所以我们作品中,只是完成了虚拟漫游,在此基础上本来是可以添加更多的漫游方式来,动态添加模型和删除也写了简单的测试。还有一个遗憾是,我们的场景是用3dmax中样条线生成的,一直有一种更好的减少面的方法没用上,就是采用低模型,展UV的方法设计场景中的模型,这样模型的面也会大大减少,模型的3d效果也会很好的表现出来。

分享到: QQ好友和群QQ好友和群 腾讯微博腾讯微博 腾讯朋友腾讯朋友 微信微信
转播转播0 分享淘帖0 收藏收藏0 支持支持0 反对反对0
回复

使用道具 举报

1274

主题

1

听众

4万

积分

禁止发言

纳金币
43676
精华
4
沙发
发表于 2012-6-1 14:27:55 |只看该作者
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

手机版|纳金网 ( 闽ICP备2021016425号-2/3

GMT+8, 2025-2-12 21:03 , Processed in 0.079247 second(s), 28 queries .

Powered by Discuz!-创意设计 X2.5

© 2008-2019 Narkii Inc.

回顶部