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.