Irrlicht学习笔记(2)--quake3map

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);
	}
}



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值