1.这个例子设计内容:
1.加载quake3map,
2.为最优化渲染速度创建一个场景节点,
3.创建可交互的摄像机.
2.加载quake3map
1)quake3map被放在一个
map-20kdm2
.pk3的压缩包中,需要加载压缩包到文件系统,
然后直接通过名字获得map.
irr::io::IFileSystem()->addZipFileArchive("../media/map-20kdm2.pk3");
这个函数内部是通过下列函数实现其功能的:
函数说明:
irr::io::IFileSystem()->getFileArchive(
const path& file,/*文件名*/
bool ignorCase = true
,/*true:加载文档后,访问内部不需要写全名字*/
bool ignorPaths = true
,/*true:加载文档后,访问内部不需要写全部路径*/
E_FILE_ARCHIVE_TYPE archiveType = EFAT_UNKNOWN,/*文档格式*/
const core::stringc& password= " "/*密码*/
);
这个函数将文档加载进文件系统,加载后,irrlicht引擎将直接从文档中搜索需要的文件,
我们用到的.pk3事实上是ZIP文件格式的,它内部调用为device->getFileArchive(filename,true,true,EFAT_ZIP);
getFIleArchive函数可以加载ZIP,PAK,TAR,PNK,和文件夹形式的文档,
我们可以编写对自己的文档类型编相应fileloader,
只需要:
1.继承IArchiveLoader 类;
2.写相应的方法;
3.传递一个instance到core::array<IArchiveLoader*> ArchiveLoader;
最后一步调用函数:void addArchiveLoader(IArchiveLoader* loader);
irrlicht支持AES加密的zip文件和高压的文件lzma,bzip2.
3.加载地图模型
1)然后从文件系统加载需要的模型文件,将地图看作是只有一帧的动画,用scene::IAnimatedMesh:
scene::IAnimatedMesh*mesh = smgr->getMesh("20kdm2.bsp");
2)然后将mesh绑定到某个mesh场景节点上.
原来的方法:
node = smgr->addMeshSceneNode(mesh->getMesh(0));
为了提高渲染效率,我们将八叉树来管理mesh:
node = smgr->addOctreeSceneNode(
mesh->getMesh(0),/*返回的是一个指针:IMesh* */
0,
-1,
1024);
函数说明:
IMeshSceneNode* addOctreeSceneNode(
IMesh* mesh,/*这个节点需要的所有网格信息的地址*/
ISceneNode* parent =0,/*八叉树父节点*/
s32 id=-1,/*节点的唯一id*/
s32 minimalPolysPerNode = 256,/*每个八叉树节点的最小面数,在小就不可分了*/
bool alsoAddIfMeshPointerZero =false/*false:如果mesh为0就不分配节点*/
);
4.为节点设置属性
载入 地图后,需要对其进行属性设置:
比如位置,缩放,旋转,方法都在irr::scene::ISceneNode中:
irr::scene::ISceneNode::setPosition(),
irr::scene::ISceneNode::setRotationi(),
irr::scene::ISceneNode::setScale();
比如我们设置坐标:
node->setPosition(core::vector3df(-1300,-144,-1249));
5.设置像机
现在地图已经在场景的何时位置了,但是运行了之后看不到它,因为还没有设置摄像机.
使用可交互的摄像机.
比如Maya中的: smgr->addCameraSceneNodeMaya();
或者FPS游戏中: smgr->addCameraSceneNodeFPS();
现在运行就看得到了,不过中间有个鼠标太碍眼,需要隐藏掉.
方法在
irr::gui::ICursorControl中,
通过irr::IrrlichtDevice获得
irr::gui::ICursorControl对象,然后调用它的方法:
device->getCursorControl()->setVisible(false);
6.添加FPS显示
最后我们在窗口标题栏添加额外的信息:
渲染驱动选择和当前fps
显示结果形如:窗口名字 [渲染设备]FPS.***
获得当前fps:通过irr:IVideoDriver::getFPS()获得当前fps,这个函数是每秒返回一次fps,
所以为了未更新就不重新显示,我们添加一个标记外部lastFPS,保存上一秒的fps:
while外:int lastFPS = -1;//需要初始化
int fps = driver->getFPS();
if(lastFPS!=fps)
{
core::stringw str = L"quake3 map ]";//窗口名字
str+=driver->getName();//渲染器
str+="] FPS":
str+=fps;//fps
//改变窗体的标题
driver->setWindowCaption(str.c_str());
lastFPS= fps;//记录
}
7详细代码:
#include <iostream>
#include <irrlicht.h>
using namespace irr;
#ifdef _IRR_WINDOWS_
#pragma comment(lib, "irrlicht.lib")
//#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup")
#endif
void mySetCreatParamters(SIrrlichtCreationParameters* cp);
void mySetDeviceType(video::E_DRIVER_TYPE* drivertype);
int main(int argc, char** argv)
{
//我们使用其他方式创建一个IrrlichtDevice
SIrrlichtCreationParameters cParam;
//mySetDeviceType(&cParam.DriverType);//2.用到的
mySetCreatParamters(&cParam);
IrrlichtDevice *device =
//1. createDevice(video::EDT_OPENGL, core::dimension2d<u32>(720, 455), 32,false, true, false, 0);
//2. createDevice(cParam.DriverType, core::dimension2d<u32>(800, 600));
createDeviceEx(cParam);//3.
if (!device)
return 1;
device->setWindowCaption(L"quake3 map");
video::IVideoDriver *driver = device->getVideoDriver();
scene::ISceneManager *smgr = device->getSceneManager();
gui::IGUIEnvironment *guiev = device->getGUIEnvironment();
//为了显示quake3 map,我们要加载它,而其被压缩在map-20kdm2.pk3中,
//所以先将压缩包加载到文件系统
//实际调用device->getFileArchive(filename,true,true,EFAT_ZIP);
device->getFileSystem()->addZipFileArchive("../media/map-20kdm2.pk3");
//将地图当作一帧动画加载
scene::IAnimatedMesh* mesh = smgr->getMesh("20kdm2.bsp");
scene::ISceneNode* node = 0;
if (mesh)
{
node = smgr->addOctreeSceneNode(mesh->getMesh(0),0,-1,1024);
//node = smgr->addMeshSceneNode(mesh->getMesh(0));
}
//通过irr::scene::ISceneNode层的方法对node进行属性调整
//位置:irr::scene::ISceneNodeirr::scene::ISceneNode::setPosition()
//旋转:irr::scene::ISceneNode::setRotation()
//缩放:irr::scene::ISceneNode::setScale();
if (node)
{
node->setPosition(core::vector3df(-1300, -144, -1249));
// node->setRotation(core::vector3df(0, 0, 0));
// node->setScale(core::vector3df(1, 1, 1));
}
//万事俱备,只需要添加一台摄像机,
//maya型的摄像机:irr::scene::ISceneManager::addCameraSceneNodeMaya()
//FPS:irr::scene::ISceneManager::addCameraSceneNodeFPS()
smgr->addCameraSceneNodeFPS();
//隐藏鼠标:irr::IrrlichtDevice::ICursorControl
device->getCursorControl()->setVisible(false);
int lastFPS = -1;
while (device->run())
{
if (device->isWindowActive())
{
driver->beginScene(true, true, video::SColor(255, 100, 101, 140));
smgr->drawAll();
guiev->drawAll();
driver->endScene();
int fps = driver->getFPS();
if (lastFPS != fps)
{
core::stringw str = L"quake3 map [";
str += driver->getName();
str += "]FPS.",
str += fps;
device->setWindowCaption(str.c_str());
lastFPS = fps;
}
}
else
//防止一直渲染占用过多cpu
device->yield();
}
device->drop();
return 0;
}
void mySetCreatParamters(SIrrlichtCreationParameters* cp)
{
std::cout << "Please select the driver you want:\n"
"(a) opengl\n(b)Direct3D 9.0c\n(c)Direct3D 8.1\n"
"(d)Burning's Software render\n(e)Software Renderer\n"
"(f)NullDevice\n(otherKey exit\n\n";
char i;
std::cin >> i;
switch (i)
{
case 'a':
cp->DriverType = video::EDT_OPENGL;
break;
case 'b':
cp->DriverType = video::EDT_DIRECT3D9;
break;
case 'c':
cp->DriverType = video::EDT_DIRECT3D8;
break;
case 'd':
cp->DriverType = video::EDT_BURNINGSVIDEO;
break;
case 'e':
cp->DriverType = video::EDT_SOFTWARE;
break;
default:
exit(1);
}
cp->DeviceType = EIDT_BEST;
cp->WindowSize = core::dimension2d<u32>(800, 600);
cp->Bits = 16;
cp->ZBufferBits = 16;
cp->Fullscreen = false;
cp->Stencilbuffer = false;
cp->Vsync = false;
cp->AntiAlias = 0;
cp->WithAlphaChannel = false;
cp->Doublebuffer = true;
cp->IgnoreInput = false;
cp->Stereobuffer = false;
cp->HighPrecisionFPU = false;
cp->EventReceiver = 0;
cp->WindowId = 0;
cp->LoggingLevel = ELL_INFORMATION;
}
void mySetDeviceType(video::E_DRIVER_TYPE* drivertype)
{
std::cout << "Please select the driver you want:\n"
"(a) opengl\n(b)Direct3D 9.0c\n(c)Direct3D 8.1\n"
"(d)Burning's Software render\n(e)Software Renderer\n"
"(f)NullDevice\n(otherKey exit\n\n";
char i;
std::cin >> i;
switch (i)
{
case 'a':
*drivertype =video::EDT_OPENGL;
break;
case 'b':
*drivertype = video::EDT_DIRECT3D9;
break;
case 'c':
*drivertype = video::EDT_DIRECT3D8;
break;
case 'd':
*drivertype = video::EDT_BURNINGSVIDEO;
break;
case 'e':
*drivertype = video::EDT_SOFTWARE;
break;
default:
exit(1);
}
}