Önceki örneklerdeki gibi başlıyoruz. Bu sefer dikkat edeceğimiz nokta, "createDevice()" metodundaki
'shadows' parametresini 'true' olarak giriyoruz. Amacımız animasyonlu bir karakterin dinamik olarak gölge
oluşturmasını sağlamak. Eğer bu örnek çok yavaş çalışırsa bunu 'false' yapın.
Irrlicht motoru donanımınızın "stencil buffer"'ı destekleyip desteklemediğini kontrol edecek ve gerekirse iptal edecektir.
#include <irrlicht.h>
#include <iostream>
using namespace irr;
#pragma comment(lib, "Irrlicht.lib")
int main()
{
// ask user for driver video::E_DRIVER_TYPE driverType;
printf("Please select the driver you want for this example:\n"\ " (a) Direct3D 9.0c\n (b) Direct3D 8.1\n (c) OpenGL 1.5\n"\ " (d) Software Renderer\n (e) Apfelbaum Software Renderer\n"\ " (f) NullDevice\n (otherKey) exit\n\n");
char i; std::cin >> i;
switch(i) { case 'a': driverType = video::EDT_DIRECT3D9;break; case 'b': driverType = video::EDT_DIRECT3D8;break; case 'c': driverType = video::EDT_OPENGL; break; case 'd': driverType = video::EDT_SOFTWARE; break; case 'e': driverType = video::EDT_SOFTWARE2;break; case 'f': driverType = video::EDT_NULL; break; default: return 1; }
// create device and exit if creation failed IrrlichtDevice *device = createDevice(driverType,
core::dimension2d<s32>(640, 480), 16, false, true);
if (device == 0)
return 1;
video::IVideoDriver* driver = device->getVideoDriver();
scene::ISceneManager* smgr = device->getSceneManager();
|
Mekan olarak bir .3ds dosyası yüklüyoruz. Bu ufak bir oda, Anim8or ile modellenmiş ve
3ds olarak export edilmiş. Motoru yazan programcı kötü bir tasarımcı olduğunu ve bu yüzden
doku yerleşiminin(texture mapping) kötü olduğunu söylüyor. Bu sebeple burada Irrlicht motorunun
güzel bir özelliğinden faydalanarak dokuyu uygun bir şekilde yerleştirmemizi sağlayacak "mesh manipulator" nesnesini
kullanıyoruz. Bu işi(planar texture mapping) yapan satırı kaldırırsanız asıl doku kaplamasını görebilirsiniz.
Programcımız Anim8or'da materyalide düzgün ayarlayamamış, burada "emissive light" özelliği iptal edilmiş.
scene::IAnimatedMesh* mesh = smgr->getMesh(
"../../media/room.3ds");
smgr->getMeshManipulator()->makePlanarTextureMapping(
mesh->getMesh(0), 0.008f);
scene::ISceneNode* node = 0;
node = smgr->addAnimatedMeshSceneNode(mesh);
node->setMaterialTexture(0, driver->getTexture("../../media/wall.jpg"));
node->getMaterial(0).EmissiveColor.set(0,0,0,0); |
Şimdi ilk özel efekt : Animasyonlu su. Şu şekilde çalışıyor: WaterSurfaceSceneNode bir mesh'i input olarak alıyor
ve onun bir su yüzeyi gibi dalgalanmasını sağlıyor. Birde bu meshin materyalini "MT_REFLECTION_2_LAYER" olarak ayarlayınca
ortaya güzel bir efekt çıkıyor. Bu işleri aşağıdaki kısa kod parçacığı ile yapıyoruz. İnput olarak
bir "hill plane mesh" veriyoruz tabi buradaki düz bir yüzey. Aslında burada herhangi bir mesh'i input olarak
verebiliriz, hatta denemek için odanın kendisini verebilirsiniz, çok ilginç olacaktır.
mesh = smgr->addHillPlaneMesh("myHill",
core::dimension2d<f32>(20,20),
core::dimension2d<s32>(40,40), 0, 0,
core::dimension2d<f32>(0,0),
core::dimension2d<f32>(10,10));
node = smgr->addWaterSurfaceSceneNode(mesh->getMesh(0), 3.0f, 300.0f, 30.0f);
node->setPosition(core::vector3df(0,7,0));
node->setMaterialTexture(0, driver->getTexture("../../media/stones.jpg"));
node->setMaterialTexture(1, driver->getTexture("../../media/water.jpg"));
node->setMaterialType(video::EMT_REFLECTION_2_LAYER);
|
2. özel efekt çok basit, eminim diğer Irrlicht örneklerinden birinde görmüşsünüzdür: Bir transparan
billboard ve buna iliştirilmiş bir ışık. Sadece bir ışık node'u oluşturup etrafta gezinmesini sağlıyoruz.
Işık node'una iliştirdiğimiz bir billboard ile daha güzel bir görünüm oluşuyor ve ışığın bir kaynağı
varmış gibi gözüküyor.
// create light
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();
// attach billboard to light
node = smgr->addBillboardSceneNode(node, core::dimension2d<f32>(50, 50));
node->setMaterialFlag(video::EMF_LIGHTING, false);
node->setMaterialType(video::EMT_TRANSPARENT_ADD_COLOR);
node->setMaterialTexture(0, driver->getTexture("../../media/particlewhite.bmp"));
|
Bir sonraki efeckt çok daha ilginç: Partikül sistemi.
Irrlicht motorundaki partikül sistemi gayet modüler ve geliştirilebilinir vede kullanımı çok kolay.
Bir partikül sistemi node'u bulunmakta ve bu node'a partikül yayıcılar(emitters) ekleyebiliyoruz.
Bu yayıcılar yön, miktar, renk gibi birçok parametreye sahip olduklarından çok kullanışlılar.
Değişik tipte yayıcılar var, mesela bir nokta yayıcısı partiküllerin sabit bir noktadan çıkmalarını sağlar.
Eğer motordaki yayıcılar sizin için yeterli değilse kendiniz kolayca yenilerini yapabilirsiniz. Tek yapmanız gereken
"IParticleEmitter" arayüzünden kalıtlayan bir sınıf yazmak ve bunu setEmitter() metodu ile partikül sistemine eklemek.
Bu örnekte bir kutu yayıcısı oluşturuyoruz. Parametreler kutuyu, partiküllerin yönünü, saniyede üretilecek
minumum ve maximum partikül sayısını, partiküllerin rengini, partiküllerin minumum ve maximum yaşam sürelerini belirler.
Sadece partikül yayıcılar ile yetinmeyip, partikül etkileyicilerde(particle affectors) kullanabiliyoruz.
Bunları kullanarak yerçekimi yada rüzgar gibi etkileri partiküllere yansıtabiliriz.
Bu örnekte kullanacağımız etkileyici partikülün rengini değiştirerek zamanla görünmez olmasını sağlayacak.
Partikül yayıcılar gibi etkileyicileride kendiniz yazabilirsiniz. Yine "IParticleAffector" sınıfından kalıtlayıp,
"addAffector()" şeklinde olacak. Partikül sistemine hoş bir materyalde ekleyince
güzel görünümlü bir kamp ateşi elde ediyoruz. Materyal, doku, partikül yayıcısı ve etkileyicilerin
parametleri ile oynayarak duman, yağmur, patlama, kar vb. efektler elde edebiliriz.
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<f32>(20.0f, 10.0f));
scene::IParticleEmitter* em = ps->createBoxEmitter(
core::aabbox3d<f32>(-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("../../media/particle.bmp"));
ps->setMaterialType(video::EMT_TRANSPARENT_VERTEX_ALPHA); |
Son olarak, animasyonlu karakterimizden dinamik olarak gölge oluşmasını istiyoruz.
Bunun için bir DirectX .x modeli yükleyip mekanımıza yerleştiriyoruz.
Gölgeyi oluşturmak için sadece "addShadowVolumeSceneNode()" metodunu çağırmamız yeterli.
Gölgenin rengi sadece "ISceneManager::setShadowColor()" metodu ile global olarak değiştirilebilinir.
Eklediğimiz karakter bu sahne için biraz küçük olduğunda "setScale()" metodu ile ayarlıyoruz.
Modelimiz dinamik ışık ile ışıklandırıldığından yüzey normallerini düzeltmemiz gerekiyor. Bir modelin
boyutu (1,1,1) den farklı olduğunda bunu her zaman yapmamız gerekiyor çünkü normalleride boyutlandırdığımızdan
model çok aydınlık yada çok karanlık gözükecektir.
mesh = smgr->getMesh("../../media/dwarf.x");
scene::IAnimatedMeshSceneNode* anode = 0;
anode = smgr->addAnimatedMeshSceneNode(mesh);
anode->setPosition(core::vector3df(-50,20,-60));
anode->setAnimationSpeed(15);
// add shadow
anode->addShadowVolumeSceneNode();
smgr->setShadowColor(video::SColor(220,0,0,0));
// make the model a little bit bigger and normalize its normals // because of this for correct lighting anode->setScale(core::vector3df(2,2,2)); anode->setMaterialFlag(video::EMF_NORMALIZE_NORMALS, true);
|
Son olarak herşeyi çizdiriyoruz.Hepsi bu kadar.
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"Irrlicht Engine - SpecialFX example ["; str += driver->getName(); str += "] FPS:"; str += fps;
device->setWindowCaption(str.c_str()); lastFPS = fps; }
}
device->drop();
return 0;
}
|
|