follow my heart...
分类:
2006-11-26 19:29:07
Irrlicht引擎是一个用C++书写的高性能实时的3D引擎,可以应用于C++程序或者.NET语言中。通过使用(Windows平台),OpenGL 1.2或它自己的软件着色程序,可以实现该引擎的完全跨平台。尽管是开源的,该Irrlicht库提供了可以在商业级的3D引擎上具有的艺术特性,例如动态的阴影,粒子系统,角色动画,室内和室外技术以及碰撞检测等(见图1)。
图1.Irrlicht 3D引擎 |
图2:基于Irrlicht的游戏Yet Another Space Shooter(YASS),这里显示的是一个静态游戏帧中的令人吃惊的着色效果 |
图3.结合动态的光和水进行的场景着色 |
#i nclude #i nclude using namespace irr; #pragma comment(lib, "Irrlicht.lib") int main() { //让我们假定用户在本例中使用OpenGL //当然,也可以指定DirectX 8, 9, 等等. video::E_DRIVER_TYPE driverType = video::EDT_OPENGL; //创建设备,如果创建失败立即退出。 IrrlichtDevice *device = createDevice(driverType, core::dimension2d(640, 480), 16, false, true); if (device == 0) return 1; video::IVideoDriver* driver = device->getVideoDriver(); scene::ISceneManager* smgr = device->getSceneManager(); |
scene::IAnimatedMesh* mesh = smgr->getMesh("room.3ds"); smgr->getMeshManipulator()->makePlanarTextureMapping( mesh->getMesh(0), 0.008f); scene::ISceneNode* node = 0; node = smgr->addAnimatedMeshSceneNode(mesh); node->setMaterialTexture(0, driver->getTexture("wall.jpg")); node->getMaterial(0).EmissiveColor.set(0,0,0,0); |
mesh = smgr->addHillPlaneMesh("myHill", core::dimension2d(20,20), core::dimension2d(40,40), 0, 0, core::dimension2d(0,0), core::dimension2d(10,10)); node = smgr->addWaterSurfaceSceneNode(mesh->getMesh(0),3,300,30); node->setPosition(core::vector3df(0,7,0)); node->setMaterialTexture(0,driver->getTexture("water.jpg")); node->setMaterialTexture(1,driver->getTexture("stones.jpg")); node->setMaterialType(video::EMT_REFLECTION_2_LAYER); |
//创建灯光 node = smgr->addLightSceneNode(0, core::vector3df(0,0,0), video::SColorf(1.0f, 0.6f, 0.7f, 1.0f), 600.0f); scene::ISceneNodeAnimator* anim = 0; anim = smgr->createFlyCircleAnimator(core::vector3df(0,150,0),250.0f); node->addAnimator(anim); anim->drop(); // 把告示板依附到灯光 node = smgr->addBillboardSceneNode(node, core::dimension2d(50, 50)); node->setMaterialFlag(video::EMF_LIGHTING, false); node->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR); node->setMaterialTexture(0,driver->getTexture("particlewhite.bmp")); |
六、 粒子系统
下面介绍的这个特别效果更有趣:一个粒子系统。在Irrlicht引擎中,粒子系统既是组件化的,也是可扩展的,但是仍然易于使用。你只需要简单地把粒子发射器放到一个粒子系统场景结点,这样以来粒子看上去没有产生源。这些发射器可以据需要进行灵活配置,并经常带有许多参数,如粒子方向,粒子数量,以及粒子颜色等。
当然,发射器类型有区别(例如,一个点发射器能够使粒子从一个固定的点上发出粒子)。如果该引擎提供的粒子发射器还不能满足你的要求,你可以容易地创建你自己的发射器。这只需简单地从IParticleEmitter接口派生一个新类并使用setEmitter()方法把它依附到粒子系统上去即可。
下一个实例将创建一个盒子粒子发射器。你可能已经猜出,它从一个跳跃的盒中随机生成粒子。由参数来定义盒子,粒子的方向,每秒产生粒子的最小和最大数目,颜色以及粒子的最小和最大生命周期。
一个完全由发射器组成的粒子系统将是令人生厌的,因为缺乏真实感。因此,Irrlicht支持粒子影响器-它负责在粒子到处飞扬时予以修整。一旦添加到粒子系统上,它们就能模仿另外的更真实的效果,象重力或风。在本例中的粒子影响器只是简单地修改粒子的颜色来产生一种淡出效果。
可能你已经猜出,粒子影响器是通过派生IParticleAffector接口实现的,然后通过使用addAffector()方法把它添加到粒子系统上去。在你为该粒子系统设置了一种好看的材质后,你就有了一个看上去相当酷的野外宿营火的效果。通过调整材质,纹理,粒子发射器,还有影响器参数,你能容易地创建烟雾,下雨,爆炸,下雪等效果:
scene::IParticleSystemSceneNode* ps = 0; ps = smgr->addParticleSystemSceneNode(false); ps->setPosition(core::vector3df(-70,60,40)); ps->setScale(core::vector3df(2,2,2)); ps->setParticleSize(core::dimension2d(20.0f, 10.0f)); scene::IParticleEmitter* em = ps->createBoxEmitter( core::aabbox3d(-7,0,-7,7,1,7), core::vector3df(0.0f,0.03f,0.0f), 80,100, video::SColor(0,255,255,255), video::SColor(0,255,255,255), 800,2000); ps->setEmitter(em); em->drop(); scene::IParticleAffector* paf =ps->createFadeOutParticleAffector(); ps->addAffector(paf); paf->drop(); ps->setMaterialFlag(video::EMF_LIGHTING, false); ps->setMaterialTexture(0, driver->getTexture,"particle.bmp")); ps->setMaterialType(video::EMT_TRANSPARENT_VERTEX_ALPHA); |
mesh = smgr->getMesh("../../media/faerie.md2"); scene::IAnimatedMeshSceneNode* anode = 0; anode = smgr->addAnimatedMeshSceneNode(mesh); anode->setPosition(core::vector3df(-50,45,-60)); anode->setMD2Animation(scene::EMAT_STAND); anode->setMaterialTexture(0, driver->getTexture("../../media/Faerie5.BMP")); anode->addShadowVolumeSceneNode(); smgr->setShadowColor(video::SColor(220,0,0,0)); |
scene::ICameraSceneNode* camera = smgr->addCameraSceneNodeFPS(); camera->setPosition(core::vector3df(-50,50,-150)); int lastFPS = -1; while(device->run()) { driver->beginScene(true, true, 0); smgr->drawAll(); driver->endScene(); int fps = driver->getFPS(); if (lastFPS != fps) { core::stringw str = L"Campfire FX example ["; str += driver->getName(); str += "] FPS:"; str += fps; device->setWindowCaption(str.c_str()); lastFPS = fps; } } device->drop(); |