`
arec
  • 浏览: 33204 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Irrlicht 游戏引擎开发 cooliris 界面(三)

阅读更多

(三)着重于介绍如何让场景动起来,以及如何获取和处理消息。

源码:example_3.zip

 

1. Irrlicht 的运动机制

 

所谓运动,实际上计算机在不停得绘制场景,每绘制一次称之为一帧。 当各帧中物体的位置或外观有所变化,那么它就动起来了。 在irrlicht中,绘制一帧是在run循环中完成的:

 

    while (device->run())
    {
        if (device->isWindowActive())
        {
            driver->beginScene(true, true, video::SColor(0, 0, 0, 0));
            scene_mgr->drawAll();  // 绘制一帧
            driver->endScene();
        }
    }
    device->drop();

 

我们所要做的,就是在 drawAll() 函数中,更新物体的位置,那么场景就动起来了。

 

所有的一切,都与 scene::ISecenNodeAnimator 这个接口相关。凡是实现这个接口的类实例,都可以通过 addAnimator() 函数加入到 ISceneNode 的 animators 列表中。

 

SceneManager 的drawAll() 函数在绘制(render)场景前,会调用 OnAnimate() 函数。这个函数是递归的,以保证加入场景中的每个 SceneNode 都被调用。 在OnAnimate() 函数中, SceneNode 的每一个 ISecenNodeAnimator 的 animateNode() 函数都会被调用,以更新 SceneNode 的位置、大小或纹理。

 

整理其调用顺序如下:

 

1. SceneManager           --> drawAll()                                   绘制一帧

2. ISceneNode               --> OnAnimate()                             SceneNode运动  

3. ISceneNodeAnimator --> animateNode(ISceneNode)       实现运动的具体函数

4. SceneManager           --> render()                                    绘制

 

可见,只要实现 ISecenNodeAnimator 接口,并加入到 SceneNode 中,就能够让其动起来。

 

2. Irrlicht 的消息传递

 

Irrlicht消息的传递是从device->run()开始的,在windows中首先调用 WndProc() 收集消息,打包成其内部的SEvent结构,再由 postEventFromUser() 将消息依次传递给 UserReceiver, GUI 和 3D Scene。

 

Irrlicht 中所有处理消息的类都必须实现 IEventReciever 接口。UserReceiver 就是在CreateDevice函数中指定的一个 IEventReceiver。 也就是说,消息处理的优先级为 UserReceiver > GUI > 3D Scene。

 

在我们的程序中,并没有指定UserReceiver,暂时也没有GUI,所以消息直接交给了 SceneManager。

SceneManager 的消息,也由 ISceneManager 的 postEventFromUser() 传递。 这个函数的实现如下:

 

bool CSceneManager::postEventFromUser(const SEvent& event)
{
	bool ret = false;
	ICameraSceneNode* cam = getActiveCamera();
	if (cam)
		ret = cam->OnEvent(event);

	_IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX;
	return ret;
}

 

也就是说,只有当前Active(有效)的 ICameraSceneNode 才会接收到消息。ICameraSceneNode 会检测ISceneNodeAnimator 的isEventReceiverEnabled(), 如果为真则调用其 OnEvent 函数。

 

整理消息传递的机制如下:

 

1. IrrlichtDevice              --> run()                                       搜集消息并打包

2. IrrlichtDevice              --> postEventFromUser()             传递消息到userReceiver GUI 和 Scene

3. ISceneManager          --> postEventFromUser()             传递消息到CameraNode

4. ICameraSceneNode   --> onEvent()                                调用 Animator 的onEvent

5. ISceneNodeAnimator --> onEvent()  // if enabled           响应消息。

 

可见,实现 ISceneNodeAnimator 虽然可以 SceneNode 动起来,但只有在 CameraSceneNode 上,才能够接收和处理消息。

 

3. 实现CameraAnimator

 

如果我们实现一个 CameraAnimator,在其中处理消息,更新 CameraNode 和 CubeNode 的位置,就可以实现交互和动画。该类关键的几个函数如下:

 

class CameraAnimator : public ISceneNodeAnimator
{
public:
	//! Constructor
	CameraAnimator(...

	//! Destructor
	virtual ~CameraAnimator(){};

	//! 更新 SceneNode 位置
    virtual void animateNode(ISceneNode* node, u32 timeMs);

	//! 处理消息
    virtual bool OnEvent(const SEvent& event);

	//! This animator will receive events when attached to the active camera
	virtual bool isEventReceiverEnabled() const
	{
		return true;  // 必须为true才能接收消息
	}

        .... // other member functions.
private:
     ... // fields
};

 

需要实现的关键有三点:

(1) 拖拽时, 场景跟着移动

(2) 单击某个图片时,场景移动到该位置,图片突出显示

(3) 滚轮实现缩放

 

在编程时有以下几个关键点:

(1) 三维场景中Node的选取,还好 irrlicht 替我们实现了这点,只需如下代码,就可以将鼠标点击处的node选取出来:

 

core::position2d<s32> mouse_position(event.MouseInput.X, event.MouseInput.Y);
ISceneNode* node = scene_manager_->getSceneCollisionManager()
        ->getSceneNodeFromScreenCoordinatesBB(mouse_position, -1);

 

(2) 运动的实现

 

    包括三个运动: CameraNode 的位置, CameraNode 的拍摄点,选取的图片的位置

    CameraNode的位置决定了场景的移动;

    CameraNode 的拍摄点决定了拍摄的角度,可以实现场景的倾斜;

    被选取的图片的位置可以使其比其它图片更接近Camera,实现突出的效果。

 

    (二)中描述的图片位置是排布在 z = 0 这个平面上的,Camera 的位置在 z = -700 平面上,初始拍摄点为原点。

 

    camera拍摄点(target)在 X 轴移动的处理如下:

if (is_drag_ && current_node_ == NULL) // 拖拽
{
	core::position2di mouse_position = device_->getCursorControl()->getPosition();
	s32 xdiff = drag_start_point_.X - mouse_position.X;
	drag_start_point_ = mouse_position;

	x_target += 0.01*xdiff / core::max_(dt, 0.0000001f);
}

if (current_node_!=NULL) // 选取了某幅图片
{
	x_target = current_node_->getPosition().X;
}

sign = (x_target < x_current) ? -1 : 1;
x_speed = sign*sqrt(abs(x_target - x_current)) * 50;  // 运动速度
target_position.X += x_speed * dt;  // 移动位置

 

    在 Y 轴和 Z 轴方向的移动,包括图片的移动, 均用类似的方式处理。参见(animateNode)函数。

 

(3) 鼠标滚轮实现缩放

    只需要改变 Camera 在Z轴的位置,作简单的限幅即可:

z_target += 100*event.MouseInput.Wheel; 

if (z_target > -200)
{
	z_target = -200;
}
if (z_target < -3000)
{
	z_target = -3000;
}

 

4.最后

 

最后我们还需要将实现的 animator 附加到 Camera 上:

 

scene::ICameraSceneNode* camera = scene_mgr->addCameraSceneNode(0, 
    core::vector3df(0,0,-700), 
    core::vector3df(0,0,0), 0);
scene::CameraAnimator* animator = new scene::CameraAnimator(wall_mgr->GetWallItemList(), 
    device, scene_mgr, 
    device->getTimer()->getTime());
camera->addAnimator(animator);
animator->drop();

 

编译运行后,您应该能够用鼠标实现类似 cooliris 的交互。更进一步的完善,还需要支持键盘等……

 

p.s.

 

3d 界面就介绍到这里了,也算告一段落。

还有两个部分:

(1) GUI: 介绍GUI编写,并加入Truetype中文字体支持;

(2) AnimatedGUI:介绍目录浏览控件的编写,实现一个皮肤系统。

 

由于临近毕业,导师催着要论文,过段时间再继续吧。

鉴于本人的学习经历,劝各位千万不要盲目读研,不要盲目崇拜名校,别被糟蹋了。

我是学机械方向的,盲目接受了当年所谓的推研资格。sigh~~学术气氛糟糕啊……

 

16
0
分享到:
评论
6 楼 fr_han 2012-08-15  
运行时,为什么我看不到纹理呢?环境是:xp+vs2010+irrlicht 1.7.3,请多指教!
5 楼 yiluotianya 2012-04-25  
支持楼主,希望继续,对我们都很有帮助
4 楼 kira0001 2012-04-17  
CameraAnimator的is_first_, 似乎从来没有被用到过,它一直是false……
3 楼 xy121z 2011-03-14  
写的不错,尤其是例子3,场景的运动,对我帮助很大,谢谢
2 楼 arec 2009-05-14  
baby66 写道

有时间继续写下去呀
支持你 写得很详细


过段时间吧。还在忙论文呢。
1 楼 baby66 2009-05-11  
有时间继续写下去呀
支持你 写得很详细

相关推荐

    Irrlicht 游戏引擎开发 cooliris 界面(二)

    在本篇博文中,我们将深入探讨"Irrlicht游戏引擎"的开发,并结合"cooliris界面",为你揭示如何创建一个视觉效果出众的游戏体验。 Irrlicht是一个开源的3D游戏引擎,以其高效能和易用性著称,尤其适合初学者进行游戏...

    3D游戏引擎irrlicht

    《Irrlicht 3D游戏引擎入门指南》 Irrlicht,中文译为“鬼火”,是一款备受赞誉的开源3D游戏引擎。以其简洁的结构、高效的执行性能和易上手的特点,它不仅适合初学者学习3D游戏引擎的基础知识,也是小型3D应用开发...

    irrlicht 3D 游戏引擎源码

    总的来说,irrlicht 3D游戏引擎是学习和开发3D游戏的理想选择,无论你是初学者还是经验丰富的程序员,都能从中受益。通过深入探索这个源码包,你可以提升你的3D图形编程技能,了解游戏引擎背后的复杂机制,并可能...

    Irrlicht创建游戏GUI界面(演示程序+源代码)

    Irrlicht游戏引擎自带了GUI模块,可以在三维的场景中创建二维的覆盖(Overlay),使得游戏中图标和文字的显示更为方便,配合游戏高效的三维渲染能力,相得益彰。 这一次我将尝试用代码对GUI进行显示,我们的目标是...

    DirectX 3D游戏引擎Irrlicht教程合集.zip

    DirectX 3D游戏引擎Irrlicht教程合集

    irrlicht 引擎

    irrlicht引擎是一款强大的开源3D游戏引擎,专为实时3D渲染设计,广泛应用于游戏开发、虚拟现实场景和图形演示。这款引擎最初由Nikolai Ostertag开发,并在GPL许可证下发布,允许开发者自由地使用、修改和分发其源...

    用IRRLICHT3D引擎写RPG游戏的框架

    irrlicht3d 引擎是开源的3D图形库,专为实时应用,尤其是游戏开发设计。本项目“用IRRLICHT3D引擎写RPG游戏的框架”提供了一个完整的RPG游戏开发基础,包括工程文件和源代码,旨在帮助开发者快速构建自己的角色扮演...

    irrlicht 1.6 游戏引擎下载

    irrlicht-1.6 是一个基于C++的开源游戏引擎,专为开发2D和3D游戏而设计。它的名称“irrlicht”在德语中意为“不真实的光”,暗示了它在渲染和光照方面的强大能力。该引擎最初由德国开发者Nikolaus Gebhardt在2003年...

    在Qt中使用Irrlicht3D引擎

    在Qt中集成Irrlicht3D引擎,可以创建出丰富的3D图形用户界面,为桌面应用和游戏开发带来强大的视觉效果。Irrlicht是一个开源的3D渲染引擎,以其易于使用和高性能而受到开发者欢迎。Qt则是一个跨平台的C++开发框架,...

    Irrlicht(鬼火)3D游戏引擎0.1版源代码

    示例项目可以用来快速上手,理解如何使用Irrlicht引擎开发游戏。文档部分可能包含API参考、教程和用户指南,帮助初学者理解引擎的用法。 Irrlicht引擎的另一大优点是其易于集成到其他项目中。它提供了多种编程语言...

    鬼火irrlicht开源3D游戏引擎1.7.2

    鬼火Irrlicht开源3D游戏引擎1.7.2 Irrlicht是一个开源的3D游戏引擎。它具有高效,实时等特点,是个完全跨平台的引擎,使用D3D、OpenGL和它的自己的渲染程序。支持动态的阴影,粒子系统,角色动画,室内和室外技术以及...

    Irrlicht引擎学习教程

    Irrlicht引擎是一款开源的3D游戏引擎,专为实时3D应用设计,如视频游戏、模拟软件等。这个教程集合提供了全面的学习资源,包括对Irrlicht Engine的深入理解和OpenGL开发环境的配置。 Irrlicht Engine的核心特性在于...

    Irrlicht引擎(鬼火游戏引擎 C++版)SVN版本

    然而,因为Irrlicht主要由游戏名家Nikolaus Gebhardt所设计,所以该游戏在设计上十分连贯。你可以在网上到处发现有Irrlicht的增强程序,如可选用的地形生成器,入口生成器,输出器,world层生成器,相关教程和编辑器...

    Irrlicht引擎例子说明及中文

    Irrlicht引擎是一款开源的3D图形引擎,专为游戏开发和实时三维可视化设计。这个引擎以其易用性、跨平台性和高效性能而受到开发者们的欢迎。"Irrlicht引擎例子说明及中文"压缩包文件提供了关于如何使用Irrlicht引擎的...

    Irrlicht引擎的ai库

    Irrlicht引擎是一款开源的3D图形引擎,以其高效和易用性在游戏开发和实时三维渲染领域被广泛应用。而"Irrlicht引擎的ai库"则是该引擎的一个扩展,专注于实现人工智能(AI)功能,这对于游戏中的角色行为模拟、路径...

    Irrlicht引擎(鬼火游戏引擎 C++版)v1.4

    Irrlicht引擎是一个用C++书写的高性能实时的3D引擎,可以应用于C++程序或者.NET语言中。通过使用Direct3D(Windows平台),OpenGL 1.2或它自己的软件着色程序,可以实现该引擎的完全跨平台。尽管是开源的,该...

    Irrlicht引擎_Android版

    1. **游戏开发**:Irrlicht引擎在Android上的应用最常见的是游戏开发,如简单的3D跑酷游戏、冒险游戏等,利用其强大的图形渲染能力,可以快速构建出富有视觉冲击力的游戏场景。 2. **3D模型展示**:在工业设计、建筑...

Global site tag (gtag.js) - Google Analytics