| GirişBu yazı, OpenGL uygulamaları için Mark Kilgard tarafından
          yazılmış olan  GL kullanım elaygıttakımı (Utility Toolkit) 
          GLUT ile ilgili serinin devamıdır. Daha önceki yazımızda 
          belirttiğimiz gibi (
          Pencereler ve Canlandırımlar)
          GLUT, herhangi bir OpenGL geliştiricisi için ilginç ve kullanışlı
          bir elaygıttakımıdır. Çünkü, taşınabilir düzgü (code) yazmanıza 
          olanak tanır. GLUT, pencere yönetiminin ve GUI arayüzünün altında
          yatan pis ayrıntıları geliştiriciden gizler.  GLUT, bir kesim subAPI'lere bölünmüştür. Bu ayki sayıda 
          Pencereler Yönetimi subAPI'si betimlnecektir. Adından da
          anlaşıldığı üzere, OpenGL uygulamanız tarafından kullanılan 
          pencereler ile ilgili görevlere bakar. Bu bağlamda, Yaratım, 
          yokedim, pencere ikonu olusturumu; itim, pat diye ortaya çıkarım, 
          gizlenim, hareket ettirim; başlıkların, bulunulan yerlerin 
          ayarlanımı, vs..  
           Pencere Yonetimi Sub-Api'siBurada GLUT'da pencerelerin yönetimi tarafından desteklenen
          fonksiyonların tam bir dizelgesi (listesi) verilmektedir. 
          (Sürüm 3.6): 
	  
	  | int glutCreateWindow(char *name) | Yeni bir üst düzey penceresi yaratır. |  
	  | int glutCreateSubWindow(int win, int x, int y, int width, int height)
 | Bir alt pencere yaratır. |  
	  | void glutSetWindow(int winId) | O anki pencerenin winID'si (pencere kimliği) biçimindeki ID 
          (kimlik) ile pencereyi oluşturur. |  
	  | int glutGetWindow(void) | O anki pencere için kimliklendirici ister. |  
	  | void glutDestroyWindow(int winId) | WinId tarafından belirtilen pencereyi yok eder. |  
	  | void glutPostRedisplay(void) | O anki pencerenin yeniden görüntülenme icin gereksinimi olan
          olay işlemcisini GLUT'a söyler. |  
	  | void glutSwapBuffers(void) | O anki pencere için tampon bölge değiştokuşu yapar. |  
	  | void glutPositionWindow(int x, int y) | Pencerenin konumunda değişiklik isteminde bulunur. |  
	  | void glutReshapeWindow(int width, int height) | Pencerenin ölçülerinde değişiklik isteminde bulunur. |  
	  | void glutFullScreen() | O anki pencerenin tüm ekranı kaplaması isteminde bulunur. |  
	  | void glutPopWindow(void) void glutPushWindow(void)
 | O anki pencereyi yığıttaki diğer pencerelere göre iter
          veya üste çıkarır. |  
	  | void glutShowWindow(void) void glutHideWindow(void)
 void glutIconifyWindow(void)
 | O anki pencereyi gösterir, saklar veya ikonlaştırır. |  
	  | void glutSetWindowTitle(char *name) void glutSetIconTitle(char *name)
 | Penceredeki veya ikonlaştırılmış penceredeki bağlık 
          çubuğunu ayarlar. |  Alt Pencerelerin 
           KullanımıYukar}daki fonksiyonların birçoğunun kullanımı oldukça basittir.
         Bunlardan bazıları ilk yazımızda gözden geçirilmişti:
         glutPostRedisplay, glutCreateWindow, glutPositionWindow,
         glutSwapBuffers,..vs. Diğerleri yeni olmalarına karşın
         kullanım açısından önemsizdirler ve glutSetIconTitle, 
         glutFullScreen, ...vs. hakkında yukarıdaki açıklamalar 
         işlevleri konusunda yeterlidir. Fakat alt pencerelerin
         kullanımları o kadar da basit değildir. Bu yüzden size basit bir 
         örnek vermeye ve onun kullanımı için gerekli olan 
         ayrıntıları kısaca tartışmaya karar verdik. 
        
           Aşağıda küçük bir OpenGL-GLUT örnekgösterimi (demo) icin kaynak 
         düzgüsü (kodu) sunulmaktadır. (../../common/March1998/example1.c, 
         ../../common/March1998/Makefile). Bu örnekgösterimin amacı size:
         (a) Bir alt pencerenin nasıl yönetileceğini, 
         (b) Klavyenizin OpenGL uygulamanız ile etkileşimli olarak nasıl
         kullanılabilecegini,        
         (c) Bir OpenGL penceresinde bir metni nasıl görüntüleştireceğinizi
         (render) göstermektir.(Tartışmaları izlerken ../../common/March1998/example1.c'nin kaynak düzgüsünün çıktı
         olarak bir biçimde elinizde olmasıná lutfen özen gösteriniz.) 
 
 ![[Snapshot of example1 running]](../../common/March1998/glut2.jpg) 
  İlk önce main() fonksiyonuna bir göz atalım. Diğer GLUT
         uygulamalarında olduğu gibi başlangıç tanımlamaları ile başlıyor:
         Güdüm satırı seçeneklerinin yazılması, görıntı kipinin seçilmesi,
         öncelikli pencerenin yerinin ve boyutunun ayarlanması. 
         Uygulamamızın birden çok pencerenin yönetimine yönelik olmasindan 
         dolayı, glutCreateWindow tarafından verilen tamsayı 
         değerli pencere kimlik (ID) numarasını depolamak önemlidir. 
         winIdMain değişkeni pencere tutamağıdır (handle). 
         Bundan sonra, winIdMain penceresi ile ilgili olaylar
         içn geriçağırım (callback) fonksiyonlarının ayarlanmasına sıra gelir.
         Birçok geriçağırım (callback) fonksiyonu tanımlanır ve tümü 
         ana pencerede bir görev üstlenir: görüntüyü çizen 
         (mainDisplay) görüntü fonksiyonu, pencere çerçevelerinin 
         tüm dönüşımlerini yöneten (mainReshape) fonksiyonu, 
         klavye ve baska olayların sırada beklemediği zaman canlandırımı 
         (animasyonu) yöneten boşakoşum (idle) tarafından başlatılan
         etkinlikleri yöneten klavye. (idle'nin rolunun daha 
         ayrıntılı anlatımı için 
         Pencereler ve Canlandırımlar bölümüne bakınız.) Bilinmesi gereken ilk önemli konu, bir GLUT uygulamasında 
         yalnızca bir tane boşakoşan geriçağırım (callback) 
         fonksiyonu olabileceğidir. Uygulamada boşakoşum (idle) fonksiyonu 
         tım pencereler icin bütüneyaygındır (global). Bunu, idle()
         fonksiyonlarinızı biçimlendirirken dikkate alınız. Tüm pencerelerin
         ve alt pencerelerin yenilenmesinde uygulamanızda görev
         almalılardır.  Program düzgüsüunde (kodunda) bir alt pencerenin yaratılması
         gelir (winIDSub). Alt pencere yapmak için üst düzey
         pencereye bir kimlik (ID) sağlamak gerekir. Bulunulan durumda 
         ilgili alt pencerenin winIDMain'in iç koordinatlarına göre  
         piksel türünden x ve y koordinatları ve istenilen alt pencerenin 
         piksel türünden yükseklik ve genişliği kimlik olarak düşünülebilir. 
         Alt pencereyi yarattıktan sonra GLUT programımıza bir tutamak 
         (handle) gönderir ve winIDSub için uygun geriçağırım
         (callback) fonksiyonlarının ayarlanması için hazır duruma gelinir.
         Örnekgösterimimizde iki tane geriçağırım (callback) fonksiyonunun 
         ayarını yapmaktayız: görüntü (subDisplay) ve yeniden biçimlendirme 
         (subReshape).  GLUT bir alt pencere açtığında, bunu tüm OpenGL çevre koşulları
         ile destekler. Alt pencerelerin kullanımı sırasında bir başarım
         (performans) kısıtı ortaya çıkar. Çünkü, grafik kartının 
         sürücüsü pencereler arası her geçişte bu pencereler için ayrılmış 
         olan bellek alanlarını yenilemek zorundadır. Her pencere bağımsız 
         OpenGL koşulları sayesinde kendi koordinat sistemine sahiptir. 
         ../../common/March1998/example1.c' de koordinat sistemleri sırasıyla mainDisplay() 
         ve subDisplay()' da ayarlanmıştır. Şimdi bu iki görüntü
         fonksiyonunu kendiniz deneyebilirsiniz ve eğer Ocak ayında OpenGL 
         hakkındaki yazımızı izlediyseniz (
          "")
           anlama konusunda bir sorun çıkmayacaktır. mainDisplay() fonksiyonu köşeleri kırmızı, yeşil ve mavi
         renklerde bir üçgen çizer. OpenGL, köşeler arasında renkleri 
         inrepolasyonla üreterek çokgeni doldurur. Üçgeni görüntüleştirmeden
         önce dönen bir şekil izlenimi elde edebilmek için, üçgenin z-ekseni 
         etrafında dönmesini (pencere ekranına dik olarak) sa\u glayan 
         glRotate deyimi eklenmiş ve dönme açısı (spin) 
         idle()' da yavaşça arttırılarak kullanılmıştır.
          winIdSub'a eçlik eden görüntü fonksiyonunda olduğu
         gibi süreç çok kestirmedir. Önce arka planı gri bir renkle 
         temizler, sonra alt pencereye yeşil bir çevreselsınır çizer 
         ve son olarak metni görüntüleştirir. GLUT altinda metin
         görüntüleştirmenin nasil yapıldığı daha sonra açıklanacaktır. 
         Bu an icin, glRasterPos2f(x, y) ile metnin nereye 
         çizileceğinin ayarlarının yapilabileceğine, ve ayni zamanda, 
         kullanılan x, y koordinatlarının alt pencerenin koordinat 
         sistemine (subReshape()' de tanımlanmıştı) göre
         verildiğine dikkat çekmek yeterlidir.   Alt pencere canlandırımdan gelen veriler icin metin ortamı
         olarak rol oynar. Bu aptalca bir uygulamadır; metin ortamı ana 
         pencerede oluşturulabilir ve aynı sonuca başarıyla ulaşılabilirdi
         (üstelik daha verimli bir şekilde). Bununla beraber, Ozel
         durumlarda metin ortamı için bir alt pencere açmak bir anlam
         kazanabilir. Ornegin, canlandırımın ışıklar ve çevresel etkilerle
         bezenmiş 3 boyutlu olması durumunda metin ortamını ışıklar, 
         perspektif etkiler, gölgelemeler ve sislerle bozmak 
         istemediğinizde geçerlidir. Böyle durumlarda alt pencere 3 boyutlu
         canlandırımdan bütünüyle ayrıldığı için kullanışlı olur. Üst düzey pencere ile alt pencere için kullanılan yeniden 
         biçimlendirme (reshape) geriçağırım (callback) fonksiyonları 
         arasında cok önemli fark bulunmaktadır. Bir yeniden 
         biçimlendirme (reshape) olayı başlatıldığında yalnızca üst 
         düzey pencere yeniden biçimlendirme geriçağırım  fonksiyonu
         (örneğimizde mainReshape()) devreye sokulur. 
         subReshape yeniden biçimlendirme geriçağırım fonksiyonu 
         mainReshape'in içinden çağrılmalıdır. 
         Bu durum, alt pencerelerin yerleşim ve biçimlerinin üst düzey
         pencerenin büyüklük ve biçimiyle sınırlandırılmış olmasından
         dolayı etkilidir. Bu yüzden, eğer mainReshape() icin 
         program düzgüsünü (kodunu) okuyacak olursanız, önce üst düzey 
         pencere için izdüşüm matrisini oluşturduğumuzu, sonra da 
         winIDsub ile belirtilen alt pencereye çevrildiğini ve 
         alt pencerenin yeniden biçimlendirme fonksiyonunun
         sonradan kullanmak istediğimiz winIDMain'e göre verilen
         yükseklik ve genişlik ile beraber çağrıldıgını göreceksiniz. OpenGL uygulamasında idle() geriçağırım fonksiyonunun 
          tum üst düzey ve alt pencereleri güncellemesi gerektiğini daha 
          önce belirtmiştik. Örneğimizde, idle() ilk once
          canlandırım durum değişkenlerini (time ve spin) 
          güncellemekte ve sonra hem ana hem de alt pencereyi yeniden 
          görüntülenmesi isteminde bulunmaktadır. KlavyePrograma iki tane etkin tuş eklenmiştir. ("i" tuşuna basarak
          metin ortamını kapatıp açabilirsiniz ve "q" tuşu ile uygulama
          ortamından çıkabilirsiniz. Deneyin, göreceksiniz :) Klavyenizden bir tuşa her bastığınızda GLUT'un olay işlemci
          sürücüsü bunu bir klavye olayı olarak yazmaçlar. Bu olaylar klavye 
          geriçağırım (callback) fonksiyonları tarafından yönetilir. 
          İlke olarak her pencere kendi geriçağırım fonksiyonuna sahiptir. 
          Fare (mouse) verilen bir pencere (veya alt pencere) içindeki
          (x, y) konumunda bulunduğunda ve bir klavye olayi başlatıldığında
          o pencere ile ilgili olan klavye geriçağırım fonksiyonu devreye
          sokulur. Bu geriçağırım fonksiyonu argümanlar olarak tuşa ait 
          olan ASCII simgesini (imlenmemiş simge: unsigned char ve 
          imlecin o anki x, y konumunu alır. ../../common/March1998/example2.c' de x, y icin bir
          kullanım sunulmamaktadır ama, bu güzel özelliğin üstünlüklerini 
          kendi uygulamalarınızda kullanacagınıza eminim.  Örnekgösterimimizde yalnızca üst düzey penceresi 
          klavye geriçağırımına sahiptir. Eger, imleç alt pencere içindeyken
          "i" veya "q" tuşlarına basarsanız hiçbir şeyin olmadığını 
          göreceksiniz. Benimsenmiş olarak, bir pencere yaratıldığında ve 
          hiç klavye geriçağırımı yazmaçlanmadığında (registered) tüm tuş 
          vuruşları gözardı edilir. Bunu, ileride birden fazla pencere 
          kullandığınızda ve klavyeyi etkinleştirmek istediğinizde 
          unutmamanız gerekir.  Son olarak, glutKeyBoardFunc().fonksiyonuna NULL
          degeri atanarak klavye geriçağırımlarının üretilmesinin 
          önlenebileceğini vurgulayabiliriz. 
           Metin GörüntüleştirimiOpenGL ve GLUT altında metin oluşturma olanaği oldukça
          yetersizdir. Bunu söylediğim için üzgünüm ama bu doğrudur. 
          OpenGL kitaplığında  metin oluşturmanın neden bu kadar 
          gözardı edildiğinden tam olarak emin değilim. SGI'in eski 
          GL kitaplığının grafik kipinde metin oluşturmayı yöneten 
          birkaç yüksek düzeyli fonksiyonu vardı ve ayrıca ek olarak da 
          fontları değiştirmek için yardımcı kitaplığı bulunmaktaydı. 
          OpenGL sıfırbirharitası oluşturmak için çok ilkel
          yönergeleri destekler ve bunun anlamı her simge için
          sıfırbirharitalarını oluşturan kitaplığı çözınırlığe, 
          fontların ölçeklerine ve bu gibi özeliklere dikkat ederek 
          kendinizin yapacak olmasıdır.  GLUT, OpenGL ile metin kullanımındaki ikilemi biraz da olsa
          çözmektedir. O, yeri glRasterPos tarafından tanımlanan 
          tek bir simgeyi ekranda oluşturan glutBitmapCharacter'i 
          sağlamaktadır. katarları olustururken yaşamı kolaylaştıran 
          drawString() ve drawStringBig() fonksiyon 
          ikilisi de ayrıca eklenmiştir.  SonuçBurada, GLUT alt pencerelerinin kullanımına çok basit bir 
          giriş yapılmış bulunulmaktadır. Bu anda, bunlarla denemeler 
          yapmanın ve değişik çalışmatabanlarında (platformlarda) 
          sınamanın yararlı olacagını belirtirken vurgulanması gereken
          nokta GLUT alt pencerelerinin, ne yazıkki, her yerde tam etkin 
          olmadığıdır. 3Dfx tabanlı kartları bulunan kullanıcılar donanım 
          kısıtlamalarından dolayi alt pencerelerin kullanımının olmadığınğ 
          goreceklerdir. Aynı zamanda, bazı özel çalışmatabanlarında
          (platformlarda) alt pencereleri kullanırken büyük bir başarım 
          sorunu bulunmuştu. Örneğin, 2Mb Matrox Millenium'lu bir Linux
          Alpha altinda bir alt pencere kullanımı uygulamanın iki kat 
          yavaş çalışmasına sebep olmaktadır. Çünkü, büyük olasılıkla 
          Alpha için olan X sunucusu halen herhangi bir donanım ivmesini 
          desteklememektedir. Öte yandan, SGI'in OpenGL sürücülü bir 
          2Mb ATI RageII'li Windows 95 altında aynı uygulama olağanüstü 
          bir şekilde çalışmaktadır.  Linux'un çok hızlı bir şekilde gelişim göstermesinden dolayı
          yakın bir gelecekte bu başarım sorunlarının ve uyumsuzlukların 
          giderilmesi çok olasıdır. Bu an için bunların farkında olup
          çoklu pencere kullanımında dikkatli olmak gerekmektedir. Kuşkusuz, üst düzey kullanıcılar matris yığıtı ile 
          oynayarak alt pencerelerin kullanımı ile ilgili bir yol 
          bulabilirler ama bunu, henüz calismamamizdan dolayı, sonraya
          bırakacağım için beni bağışlayın.. ;)).  |