Sayfalar

2 Eylül 2010 Perşembe

ogre3D ve temel sınıflar ve dosyalar – bölüm 3

Temel sınıflar yazı dizimde sıra geldi üçüncü bölüme. Bir önceki yazımda ExampleApplication sınıfından bahsetmiştim, bu seferki yazımda da ExampleFrameListener sınıfından bahsetmek istiyorum.
Şimdi öncelikle sınıfımızın içindeki değişkenlere bir göz atalım. İçlerinde en dikkat çekici nitelikte olanlar aşağıdakiler gibidir. Diğerleri de önceden bahsettiğim değişkenlerdendir. O yüzden şimdi bize yeni ve önemli olanlarla devam edelim.
  • std::string mDebugText;
  • TextureFilterOptions mFiltering;
  • Overlay* mDebugOverlay;
  • OIS::InputManager* mInputManager;
  • OIS::Mouse* mMouse;
  • OIS::Keyboard* mKeyboard;
  • OIS::JoyStick* mJoy;
"mDebugText" değişkeni strig sınıfından bir değişkendir ve tahmin edebileceğiniz gibi string ifadeler içindir.
"mFiltering" değişkeni "TextureFilterOptions" kümesinin elemanlarıdır. Bu elemanlardan "TFO_BILINEAR" constructor'da aktifleşmiş durumda. Yani projeniz "TFO_BILINEAR" filtresi aktif olacak şekilde size sunuluyor. Klavyeden " T " tuşuna bastığınız zaman küme elemanları arasında değişiklik yapıyor. Bunun ayarlamalarını da yine ExampleFrameListener'ın bir fonksiyonu halletmektedir. Ancak buna yine sonra değineceğim. Şimdi bu kümenin elemanlarıyla devam edelim. "TFO_NONE, TFO_BILINEAR, TFO_TRILINEAR, TFO_ANISOTROPIC" değerleri bizim kullanabileceğimiz değişkenlerdir. Ancak bu değişkenler arasında ne gibi farklılıklar var tam ben de emin değilim. Size aşağıdaki örnekte bu değişkenler arasındaki farkı göstermek istedim. Buradan da anlaşılabileceği gibi en düzgün görüntü veren filtre tipi TFO_ANISOTROPIC filtredir. Ancak iyi olan performansı da en çok zorlayandır mantığıyla sisteminiz iyise ve iyi optimize edilmiş kodlarınız varsa kullanmanızı tavsiye edebilirim :)




"mDebugOverlay" değişkeni de projemizi derledikten sonra karşımızla çıkan sağ alt taraftaki ogre logosu ile birlikte sol alt taraftaki debug menüsünü tutan değişkenidir.

OIS ( Object-Oriented Input System ) sınıfından üretilen değişkenler de bizim klavye fare joystick gibi birimlerin sınıfıdır dersek yanlış olmaz sanırım. "mInputManager" değişkeni de mMouse, mKeyboard ve mJoy değişkenlerinin yöneticisidir.
Değişkenler ile işlerimizi hallettikten sonra şimdi de önemli olan bazı fonksiyonlara bakalım.

"Constructor"tan başlayalım. ExampleApplication sınıfı ExampleFrameListener'dan bir nesne ürettiği zaman parametre olarak mWindow ve mCamera değişkenlerini göndermiştir. Burada da görebileceğiniz gibi constructor diğer paremetrelerini false olarak atamış bulunmakta. Peki bu false değerlerini true yaparsak ne olur? O zaman kontroller miras alınan bu sınıftan alınıp sizin üreteceğiniz kodlara kalır. Yani siz herhangi bir tanımlama yazpmazsanız ne klavyenizden gelen komutlar alınır ne de farenizden. O yüzden buraya dikkat :)
ExampleFrameListener(
RenderWindow* win,
Camera* cam,
bool bufferedKeys = false, 
bool bufferedMouse = false,
bool bufferedJoy = false 
):
Devam edelim; "mDebugOverlay = OverlayManager :: getSingleton() . getByName ("Core/DebugOverlay");" satırı, ekrandaki debug menüsü ile logoyu içerisinde barındıran "Core/DebugOverlay" değerini almıştır ve "showDebugOverlay(true);" fonksiyonuna da parametre olarak true değeri gönderilmiştir. "showDebugOverlay();" fonksiyonu da "mDebugOverlay" değişkenini gösterip kaybedecek şekilde tasarlanmıştır. Bu tasarım şekliyle de kontrol kolaylığı sağlanmıştır. Bu kolaylıktan, klavye tuşlarının ayarlandığı fonksiyona gelince bahsedeceğim.
Yine "constructor"a ait olan aşağıdaki kod satırlarında her nesne kendi sınıfının varlığı olarak yaratmış ve bunları mInputManager değişkeninin kontrolüne bağlamış. Ancak bende "try" bloğu arasında mJoy değişkeninde bir problem kendini göstermeye başladı. Sebebinden emin değilim zira önceden bu problem ortaya çıkmazdı. Şöyle kısaca problemden bahsedeyim. Kod sorunsuz derlenmekte ancak konsol ekranında bu satıra gelince program kendini kapatmataydı. Bu kod satırını iptal etmek zorunda kaldım. joystik kullanma gibi bir durumum söz konusu olmadığı için de herhangi bir probleme neden olmamakta artık.

mKeyboard = static_cast<OIS::Keyboard*>(mInputManager->createInputObject( OIS::OISKeyboard, bufferedKeys ));
mMouse = static_cast<OIS::Mouse*>(mInputManager->createInputObject( OIS::OISMouse, bufferedMouse ));
try
{
mJoy = static_cast<OIS::JoyStick*>(mInputManager->createInputObject( OIS::OISJoyStick, bufferedJoy ));
}
"virtual void updateStats(void)" fonksiyonu her karenin renderleme işlemi bitttikten sonra o karedeki hesaplanan değerlerin ( FPS değerleri ile ekranda o andaki hesaplanan üçgen sayısı gibi ) güncellenmesini sağlamaktadır.
"bool frameRenderingQueued(const FrameEvent& evt)" fonksiyonu da içerisinde bulunan değerleri o karenin renderleme işlemi bitene yani frameEnded olana kadar yapmayı sürdürmekle yükümlüdür. Tahmin edebileceğiniz gibi bir de frameStarted kısmı mevcuttur ancak frameListener'ın içinde tanımlı olan bu fonksiyonları ExampleFrameListener miras alırken frameStarted alınmamıştır. Şimdi bu fonksiyonun içeriğine bakalım.
// eğer pencere kapanırsa false değer dönder ve fonksiyonu bitir.
if(mWindow->isClosed())  return false;

// klavyeyi ve fareyi sürekli olarak yakala
mKeyboard->capture();
mMouse->capture();

// eğer klavye ve fare kontrolü ExampleFrameListener'a aitse;
if( !mMouse->buffered() || !mKeyboard->buffered() || !buffJ )
{moveCamera();
...
.
}

// eğer klavye kontrolü Listener'da ise ve klavye tuşlarının ayarlandığı
// "processUnbufferedKeyInput" fonksiyonundan false değer dönüyorsa false
// değer dönder ve programı bitir.
if( !mKeyboard->buffered() )
if( processUnbufferedKeyInput(evt) == false )
    return false;
// klavyedeki mantık ile aynı şekilde işlemekte.
if( !mMouse->buffered() )
if( processUnbufferedMouseInput(evt) == false )
return false;

Buradaki işlemlerin haricindeki diğer işlemler de hız kontrolü ile alakalıdır. O yüzden pek girmedim. Ne ben tam olarak hatim etmiş değilim ne de fonksiyonun hız mantığını kurmak ile ilgileniyorum bu yazıda. O yüzden devam ediyorum.

"bool frameEnded(const FrameEvent& evt)" fonksiyonu da karenin renderleme işlemi bitince o kareye ait hesaplama bilgilerini updateStats() fonksiyonu aracılığıyla debug penceresine göndermekle yükümlü bir fonksiyondur.

"virtual void moveCamera()" fonksiyonunda ise kameranın konumlarını o anda hesaplanan değerler çerçevesinde ayarlayan bir fonksiyondur. "mCamera->yaw(mRotX); mCamera->pitch(mRotY);" satırları kamerayı çevirirken "mCamera-> moveRelative (mTranslateVector);" kod satırı kamerayı hareket ettirmektedir aynı move() fonksiyonunun yaptığı gibi ama biraz farklı bir şekilde. Şöyle ki; X eksenine bakan bir kameranız orjinde yer almakta diyelim. Bu kamerayı hangi eksende hareket ettirirsek ettirelim hem move() hem de moveRelative() ile baktığı konumu değişmeyecektir. Ancak kamerayı bir eksende 90 derece çevirirsek işler değişmekte. Bu sefer move() fonksiyonu yine kamerayı döndermeden önceki gibi davranırken moveRelative() fonksiyonu kameranın dönmüş konumunda ilerlemesini sağlamakta. Böylece göreceli bir çevirme söz konusu olmakta...
"virtual bool processUnbufferedKeyInput(const FrameEvent& evt)" fonksiyonu da klavyeden bir tuşa basılırsa ve o basılan tuş tanımlıysa yapılacak eylemleri kontrol eder. Önemli birkaç tuş kontrolüne bir göz atalım şimdi:
// Kameranın bağlı olduğu vektörü z konumunda belirlenen mMoveScale değeri kadar hareket ettirir.
if(mKeyboard->isKeyDown(OIS::KC_UP) || mKeyboard->isKeyDown(OIS::KC_W) )

// Aynı şekilde ancak bu sefer x konumunda hareket ettirir, dikkat çevirmez.
if(mKeyboard->isKeyDown(OIS::KC_A))

// Kameranın "mCamera->yaw(-mRotScale);" kod satırı sayesinde sağa dönmesini sağlar 
if(mKeyboard->isKeyDown(OIS::KC_RIGHT))

// Çıkışı sağlar
if(mKeyboard->isKeyDown(OIS::KC_ESCAPE) || mKeyboard->isKeyDown(OIS::KC_Q) )

// Debug penceresini gizler veya gösterir
if(mKeyboard->isKeyDown(OIS::KC_F) && mTimeUntilNextToggle <= 0 )

// Filtreler arasında değişim sağlar.
if(mKeyboard->isKeyDown(OIS::KC_T) && mTimeUntilNextToggle <= 0 )

// Ekranın fotoğrafını çeker
if(mKeyboard->isKeyDown(OIS::KC_SYSRQ) && mTimeUntilNextToggle <= 0)

// Ekrandaki nesneleri Solid, Wire ve Point olarak gösterir.
if(mKeyboard->isKeyDown(OIS::KC_R) && mTimeUntilNextToggle <=0)

// Kamera hakkında bazı bilgileri verir.
if(mKeyboard->isKeyDown(OIS::KC_P) && mTimeUntilNextToggle <= 0)   
Yukarıdaki kod satırlarından da anlaşılabileceği gibi belirlenen tuşa basılırsa demekten ibaret tüm olay. Eğer klavyeden " R " tuşuna basılırsa oluşacak olan değişimi yukarıdaki resimde görebilirsiniz. Soldan sağa doğru sırayla "Point" , "Wireframe" ve "Solid" teknikleridir.

mTimeUntilNextToggle
değişkeni de tuşa basılma arasındaki süreyi ifade ediyor dersem yanlış olmaz diye düşünüyorum. Buna benzer iki tane daha bolca karşılaşacağınız değişken var. Bunlar "timeSinceLastEvent" ile "timeSinceLastFrame"dir. timeSinceLastEvent, değişkeni iki olay arasında geçen süreyi saniye cinsinden ifade etmektedir. timeSinceLastFrame de frameleri ,o anlık ekran görüntüsünü , renderlerkenki geçen süreyi temsil etmekte. Bu süre ne kadar kısa olursa projeniz de o kadar hızlı olmuştur.


"virtual bool processUnbufferedMouseInput(const FrameEvent& evt)" fonksiyonu da eğer farenin sağ tuşuna basıldıysa şeklinde ayarlanmıştır.
const OIS::MouseState &ms = mMouse->getMouseState();
if( ms.buttonDown( OIS::MB_Right ) )
"ms" farenin durumunu alıyor ve if şartı ile de bu durum kontrol ediliyor. Eğer ki sağ tuşa ( OIS::MB_Right ) basarsak ( buttonDown ) kameramız farenin konumuna göre yukarı - aşağı veya sağa - sola şeklide hareket edecek, ki bunu sağlayan mTranslateVector.x ile mTranslateVector.y'nin kullanımıdır, basmazsak da kameranın moveCamera() fonksiyonundaki " mCamera-> yaw (mRotX); mCamera-> pitch (mRotY);" satırlarının mRotX ile mRotY parametrelerini değiştirmiş oluruz. Bu şekilde de kameramız bulunduğu konumda farenin yönelimine göre bakış açısını değiştirecektir.

İşte olay bundan ibaret :) bu iki sınıfı da hallettik diyelim artık sıra geldi Ogre3D dizininin içindeki bazı önemli dosya ve klasörlere. O da artık bir sonraki yazıda.

Hiç yorum yok:

Yorum Gönder