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

经过昨天比较枯燥的准备工作后,今天我们的目标是实现本地图片载入 3D 场景,主要内容是熟悉irrlicht引擎,创建一个3D窗口,并绘制图片。

 

总共有两个示例,源代码下载:

example_1.zip

example_2.zip

 

一、irrlicht 简介

 

irrlicht 游戏引擎的分成五大块:

Core:              容器类和数学库       namespace irr::core

Scene:            三维场景绘制和管理      namespace irr::scene

Video:            图片纹理的载入和管理   namespace irr::video

GUI:                二维 GUI 控件                 namespace irr::gui

FileSystem:    文件系统读写                namespace irr::io

 

编写任何一个 irrlicht 程序,首先要获得设备指针 IrrlichtDevice* device:

 

video::E_DRIVER_TYPE driver_type = irr::video::EDT_OPENGL;
core::dimension2d<s32> screen_resolution = core::dimension2d<s32>(1280, 800);
u32 color_depth = 32;
bool is_full_screen = true;

IrrlichtDevice* device = irr::createDevice(driver_type, screen_resolution, color_depth, 
    is_full_screen);

 

driver_type为驱动类型,可以选择OPENGL,DX8 或 DX9。其余几个参数分别为分辨率,颜色深度,是否全屏。

s32, u32 为 irrlicht 定义的类型,分别对应 int 和 unsigned int。

 

获得 device 指针以后,就可以得到属于该 device 的四大块功能:

 

video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* scene_mgr = device->getSceneManager();
gui::IGUIEnvironment* gui_env = device->getGUIEnvironment();
io::IFileSystem* file_system = device->getFileSystem();

 

通过 driver 载入图片和 texture,通过 scene_mgr 为3d场景添加 irrlicht 内置支持的 mesh 等工作完成后,即可进入主循环,主循环结束时,释放 device,程序结束。其中 beginScene 的参数 SColor(alpha, r, g, b) 为背景色。

 

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

 

值得一提的是 drop() 函数。Irrlicht中大部分类都继承自一个 IReferenceCounted 的接口,类似智能指针。Irrlicht 中的惯例是不使用 delete 删除对象,而调用该接口的 drop() 函数。在添加对象的引用时,调用 grap() 函数。

 

二、创建3D场景
创建3D场景有三个步骤:(1) 通过scene_mgr添加3D物体;(2)为物体贴上纹理;(3) 添加Camera,使物体可见。
在 device->run() 之前添加如下代码
// 为场景添加一个立方体,边长100
scene::ISceneNode* cube = scene_mgr->addCubeSceneNode(100.0f);

// 载入纹理
video::ITexture* tex = driver->getTexture("box.jpg");

// 将纹理附加到立方体上
cube->setMaterialTexture(0, tex);

// 将纹理EMF_LIGHTING属性设为false
// 表示该纹理现实与光源无关,即为图片自身颜色
cube->setMaterialFlag(video::EMF_LIGHTING, false);

// 使纹理支持半透明,半透明效果与图片相同
cube->setMaterialType(video::EMT_TRANSPARENT_ALPHA_CHANNEL);

// 添加一个相机,在(700,700,-700)位置,往(0,0,0)位置拍摄。
scene::ICameraSceneNode* camera = scene_mgr->addCameraSceneNode(0, 
    core::vector3df(700,700,-700), core::vector3df(0,0,0));
 至此,您应该可以看到一个立方体在场景中央。

以上源代码和所需文件在附件 example_1.zip 中。

三、创建 3DWall

源代码参见 example_2.zip ,源代码中的内容不再逐行解释了。
Device的驱动为OPENGL,需要修改请转到 util.h 的GetDevice()函数中。
例子二中3D场景的创建,移到了era::wall::CWallManager 的 UpdateScene() 函数中:
video::ITexture* tex = era::Util::Instance()->GetDriver()->addTexture("", img);
core::vector3df size(img->getDimension().Width, img->getDimension().Height, 0.01);
wallitem = smgr->addCubeSceneNode(1, smgr->getRootSceneNode(), -1, 
    core::vector3df(400*(i/3),300*(1-(i%3)), 0), core::vector3df(0,0,0), size);
图片被当成 例子一 中 cube 的纹理,填在上面。
你也许会很奇怪,怎么这些 cube 都是扁扁的? 这都是addCubeSceneNode 的最后一个参数 size 的作用。 size将长宽设为图片相同,厚度为0.01. 这样在3D环境中就是个扁扁的图片了。
第四个参数决定了cube在3d场景中的位置core::vector3df(400*(i/3),300*(1-(i%3)), 0)。这样,图片按照如下顺序排列:
1  4  7 ....   
2  5  8  ....
3  6  .......
还值得一提的是,为了节约内存,使用了缩略图。由于irrlicht自身的缩略图算法效率很低,因此程序运行起来,需要等待比较长的时间才能将图片全部载入。另外我在 util.h 编写了 FeatherEdge() 函数,为缩略图添加了阴影(效果并不是很好,但也还过得去了)。
编译运行后,您应该能看到如下画面:

 

 

今天就到这里,下一篇,我们让它动起来

你可能感兴趣的:(游戏,.net,PHP,算法,项目管理)