15 LoadIrrFile
官方代码($sdk)\examples\15.LoadIrrFile
这个例子是从.irr文件读取一个完整的场景。早起版本的sdk里的这个例子很简单,就是使用下场景管理器里的loadScene把.irr文件载入就完事了。网上我看到几篇相关的文章,都说这例子有点脑残,其实不然。做一个游戏,将每一关的场景都写到代码里去,这方法不是不行,但实在有些糟糕,稍微有一小点改动,都需要去修改代码,而且想让非程序员去完成这事,就成非常困难的事了。个人觉着,最好的办法应该还是将游戏的场景、关卡等设置从代码里分离出来,程序通过加载这些相关文件比较好。有让非程序员修改的要求时,还能做个简易的编辑器进行修改。
从1.1版本开始,Irr引擎就支持使用.irr文件来读取和保存一个完整的场景。实际上,这个irr文件就是一个xml格式的配置文件,可以通过记事本打开它。Irr也有一个更好的专门的编辑器CopperCube(官方网站是http://www.ambiera.com/),最早叫IrrEdit,目前功能已经很强烈,可以用它做游戏,并生成各种平台运行的版本,不过是要收费的。这个编辑器里有场景编辑器和还有粒子编辑器的功能。这里就不再宣传CopperCube了,接下来看看irr载入场景文件的例子。
#include <irrlicht.h>
#include "driverChoice.h"
using namespace irr;
int main(int argc, char** argv)
{
// 询问用户使用什么驱动
video::E_DRIVER_TYPE driverType=driverChoiceConsole();
if (driverType==video::EDT_COUNT)
return 1;
//创建irr设备
IrrlichtDevice* device =
createDevice(driverType, core::dimension2d<u32>(640, 480));
// 不能创建相应驱动的irr设备则退出
if (device == 0)
return 1;
//设置irr窗口的标题
device->setWindowCaption(L"Load .irr file example");
video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();
/*现在读取一个.irr文件。irr文件能够存储整个场景的材质,纹理,粒子系统等信息。同时也可以存储场景中的所有场景接点和用户数据。为了使例子简单些,这个例子中简单的读取一下场景。想获取更多信息的话,可以看文档中关于ISceneManager::loadScene和ISceneManager::saveScene的说明。这里仅读取显示一个场景,所以仅需要使用loadScene()函数。 */
//载入场景 argv[1]是命令行启动例子时加的第一个参数。这例子里将它作为手动设置.irr文件的参数,如果没有设置该参数,就是使用默认.irr文件。
if (argc>1)
smgr->loadScene(argv[1]);
else
smgr->loadScene("../../media/example.irr");
//就这么简单,一个loadScene加上文件名就完成了!接下来仅需要再增加一个摄象机,绘制场景就行了
scene::ICameraSceneNode * camera = smgr->addCameraSceneNodeFPS(0, 50.f, 0.1f);
//创建一个Meta三角形选择器来保存几个三角形选择器
scene::IMetaTriangleSelector * meta = smgr->createMetaTriangleSelector();
/*现在,我们查找场景中的所有节点,选择所有合适的节点,并建立三角形选择器。通常情况下,一个明智的办法是通过一个节点的名称或编号信息来设置碰撞检测的节点。*/
//创建一个场景节点数组nodes
core::array<scene::ISceneNode *> nodes;
//获取所有场景节点
smgr->getSceneNodesFromType(scene::ESNT_ANY, nodes);
//遍历nodes中的所有节点,查找需要设置碰撞检测的节点
for (u32 i=0; i < nodes.size(); ++i)
{
scene::ISceneNode * node = nodes[i];
scene::ITriangleSelector * selector = 0;
//筛选节点类型
switch(node->getType())
{
//立方体节点
case scene::ESNT_CUBE:
//动画场景节点
case scene::ESNT_ANIMATED_MESH:
//三角形选择器不能作用在动画网格上,动画网格只能使用摄像机射线来进行碰撞检测,这里就是用最小包围盒进行替代,创建相应的三角形选择器。
selector = smgr->createTriangleSelectorFromBoundingBox(node);
break;
//网格节点
case scene::ESNT_MESH:
//圆环节点
case scene::ESNT_SPHERE:
// 从网格场景节点导出网格创建三角形选择器
selector = smgr->createTriangleSelector(((scene::IMeshSceneNode*)node)->getMesh(), node);
break;
//地形节点
case scene::ESNT_TERRAIN:
selector = smgr->createTerrainTriangleSelector((scene::ITerrainSceneNode*)node);
break;
//八叉树节点
case scene::ESNT_OCTREE:
selector = smgr->createOctreeTriangleSelector(((scene::IMeshSceneNode*)node)->getMesh(), node);
break;
//其他节点
default:
// Don't create a selector for this node type
break;
}
if(selector)
{
//将创建的三角形选择器添加到Meta三角形选择器,meta三角形选择器里会增加相应引用
meta->addTriangleSelector(selector);
//是否创建的三角形选择器引用,次三角形选择器将由meta选择器进行管理
selector->drop();
}
}
//网格场景节点的选择器已经添加到meta选择器中立,现在为meta选择器创建一个碰撞相应运动器。
scene::ISceneNodeAnimator* anim = smgr->createCollisionResponseAnimator(
meta, camera, core::vector3df(5,5,5),
core::vector3df(0,0,0));
//现在不再需要meta选择器了,释放引用
meta->drop();
//为摄像机装上碰撞相应运动器
camera->addAnimator(anim);
//不再需要运动器了,释放引用
anim->drop();
// 设置摄像机的位置,以确保它一来不会卡住几何体上
camera->setPosition(core::vector3df(0.f, 20.f, 0.f));
// 将摄像机对准立方体,通过getSceneNodeFromType查找场景管理器里的第一个ESNT_CUBE类型场景节点得到立方体
scene::ISceneNode * cube = smgr->getSceneNodeFromType(scene::ESNT_CUBE);
if(cube)
camera->setTarget(cube->getAbsolutePosition());
//跟以往一样,绘制一切
int lastFPS = -1;
while(device->run())
if (device->isWindowActive())
{
driver->beginScene(true, true, video::SColor(0,200,200,200));
smgr->drawAll();
driver->endScene();
int fps = driver->getFPS();
if (lastFPS != fps)
{
core::stringw str = L"Load Irrlicht File example - Irrlicht Engine [";
str += driver->getName();
str += "] FPS:";
str += fps;
device->setWindowCaption(str.c_str());
lastFPS = fps;
}
}
device->drop();
return 0;
}
例子的代码看完了,关看这些代码,会有些觉着莫名其妙,这是肯定的。还得配合着.irr文件一切看。现在就来看看例子里默认使用的场景文件example.irr文件。这是一个标准的xml文件,里面可读性非常好。
<?xml version="1.0"?>
<!-- irr_scene标签 场景管理器数据的起始标签 -->
<irr_scene>
<!-- attributes标签 irr引擎里所有能够序列化的类,自身的成员数据都存在此标签下 -->
<attributes>
<string name="Name" value="root" />
<int name="Id" value="-1" />
<vector3d name="Position" value="0.000000, 0.000000, 0.000000" />
<vector3d name="Rotation" value="0.000000, 0.000000, 0.000000" />
<vector3d name="Scale" value="1.000000, 1.000000, 1.000000" />
<bool name="Visible" value="true" />
<enum name="AutomaticCulling" value="box" />
<bool name="DebugDataVisible" value="false" />
<bool name="IsDebugObject" value="false" />
</attributes>
<!—userData 用户数据 irr序列化时预留的 方便开发者扩展时增加额外的数据 这部分是前面提到的CopperCube增加的内容-->
<userData>
<attributes>
<bool name="OccludesLight" value="false" />
</attributes>
</userData>
<!-- node标签 场景节点的起始标签,后面的type属性为场景节点的类型。加载场景文件后,场景管理器根据类型属性创建相应的场景节点 -->
<node type="mesh">
<attributes>
<string name="Name" value="" />
<int name="Id" value="-1" />
<vector3d name="Position" value="3.048694, -16.834227, -3.333332" />
<vector3d name="Rotation" value="0.000000, 0.000000, 0.000000" />
<vector3d name="Scale" value="0.200000, 0.200000, 0.200000" />
<bool name="Visible" value="true" />
<enum name="AutomaticCulling" value="box" />
<bool name="DebugDataVisible" value="false" />
<bool name="IsDebugObject" value="false" />
<string name="Mesh" value="../../media/room.3ds" />
<bool name="ReadOnlyMaterials" value="false" />
</attributes>
<!-- materials标签 场景节点的材质-->
<materials>
<attributes>
<enum name="Type" value="solid" />
<colorf name="Ambient" value="1.000000, 1.000000, 1.000000, 1.000000" />
<colorf name="Diffuse" value="1.000000, 1.000000, 1.000000, 1.000000" />
<colorf name="Emissive" value="0.000000, 0.000000, 0.000000, 0.000000" />
<colorf name="Specular" value="1.000000, 1.000000, 1.000000, 1.000000" />
<float name="Shininess" value="0.000000" />
<float name="Param1" value="0.000000" />
<float name="Param2" value="0.000000" />
<texture name="Texture1" value="../../media/wall.jpg" />
<texture name="Texture2" value="" />
<texture name="Texture3" value="" />
<texture name="Texture4" value="" />
<bool name="Wireframe" value="false" />
<bool name="GouraudShading" value="true" />
<bool name="Lighting" value="true" />
<bool name="ZBuffer" value="true" />
<bool name="ZWriteEnable" value="true" />
<bool name="BackfaceCulling" value="true" />
<bool name="BilinearFilter" value="true" />
<bool name="TrilinearFilter" value="false" />
<bool name="AnisotropicFilter" value="false" />
<bool name="FogEnable" value="false" />
<bool name="NormalizeNormals" value="true" />
</attributes>
</materials>
<userData>
<attributes>
<bool name="ReceivesShadows" value="true" />
<bool name="OccludesLight" value="true" />
</attributes>
</userData>
</node>
<!—光节点,这个节点里还有子节点,后面注意看哦-->
<node type="light">
<attributes>
<string name="Name" value="" />
<int name="Id" value="-1" />
<vector3d name="Position" value="27.366207, 20.000000, 29.173460" />
<vector3d name="Rotation" value="49.740002, 0.000000, 0.000000" />
<vector3d name="Scale" value="1.000000, 1.000000, 1.000000" />
<bool name="Visible" value="true" />
<enum name="AutomaticCulling" value="false" />
<bool name="DebugDataVisible" value="false" />
<bool name="IsDebugObject" value="false" />
<colorf name="AmbientColor" value="0.000000, 0.000000, 0.000000, 1.000000" />
<colorf name="DiffuseColor" value="1.000000, 0.501961, 0.000000, 1.000000" />
<colorf name="SpecularColor" value="1.000000, 1.000000, 1.000000, 1.000000" />
<float name="Radius" value="1000.000000" />
<bool name="CastShadows" value="true" />
<enum name="LightType" value="Point" />
</attributes>
<!—animators运动器标签,添加到节点上的运动器-->
<animators>
<attributes>
<string name="Type" value="flyCircle" />
<vector3d name="Center" value="0.000000, 20.000000, 0.000000" />
<float name="Radius" value="40.000000" />
<float name="Speed" value="0.001000" />
</attributes>
</animators>
<userData>
<attributes>
<bool name="OccludesLight" value="false" />
</attributes>
</userData>
<!—里面的子节点,一个告示板节点-->
<node type="billBoard">
<attributes>
<string name="Name" value="" />
<int name="Id" value="-1" />
<vector3d name="Position" value="0.000000, 0.000000, 0.000000" />
<vector3d name="Rotation" value="0.000000, 0.000000, 0.000000" />
<vector3d name="Scale" value="1.000000, 1.000000, 1.000000" />
<bool name="Visible" value="true" />
<enum name="AutomaticCulling" value="box" />
<bool name="DebugDataVisible" value="false" />
<bool name="IsDebugObject" value="false" />
<float name="Width" value="30.000000" />
<float name="Height" value="30.000000" />
</attributes>
<materials>
<attributes>
<enum name="Type" value="trans_add" />
<colorf name="Ambient" value="1.000000, 1.000000, 1.000000, 1.000000" />
<colorf name="Diffuse" value="1.000000, 1.000000, 1.000000, 1.000000" />
<colorf name="Emissive" value="0.000000, 0.000000, 0.000000, 0.000000" />
<colorf name="Specular" value="1.000000, 1.000000, 1.000000, 1.000000" />
<float name="Shininess" value="0.000000" />
<float name="Param1" value="0.000000" />
<float name="Param2" value="0.000000" />
<texture name="Texture1" value="../../media/particlewhite.bmp" />
<texture name="Texture2" value="" />
<texture name="Texture3" value="" />
<texture name="Texture4" value="" />
<bool name="Wireframe" value="false" />
<bool name="GouraudShading" value="true" />
<bool name="Lighting" value="false" />
<bool name="ZBuffer" value="true" />
<bool name="ZWriteEnable" value="true" />
<bool name="BackfaceCulling" value="false" />
<bool name="BilinearFilter" value="true" />
<bool name="TrilinearFilter" value="false" />
<bool name="AnisotropicFilter" value="false" />
<bool name="FogEnable" value="false" />
<bool name="NormalizeNormals" value="false" />
</attributes>
</materials>
<userData>
<attributes>
<bool name="OccludesLight" value="false" />
</attributes>
</userData>
</node>
</node>
<!—后面的内容都是场景中其他场景节点的数据,后面就不再一一罗列了-->
</irr_scene>