Home Index Search Links About Us
[LinuxFocus Image]
[Navegation Bar]
  News   Archives   Companies   Tips  

3 Boyutlu Görünüm

Yazar: Miguel Angel Sepulveda

Çeviri: Burcu Sarısoy


Diğer konuları üzerinde uzunca bir gezinimden sonra 3 boyutlu grafikleri OpenGL altında tartışmya varıyoruz. Sıze yalan söyleyerek bunun kolay olduğunu söylemenin alemi yok , çünkü kolay değil. 3 boyut uygulamalarının iyi OpenGL programcıları özellikle animasyonlar Cebir , Analitik Geometri Fizik (Mekanik) ve elbette biraz da sayısal analizde bilgili olmalılar.

 Bu serilerin kalan kısmını herkes için elimden geldiğince anlaşılır düzeye indirmeye çalışacağım. Maalesef gereken şeylerden sadece bir kaçı olan  eğriye polinomik (polynomial) yaklaşım yüzeyler ve düzlemin üç boyutlu uzaydaki matematiksel gösterilimi , vektörler, matrisler hakkındaki bilgileri size veremem.

  Geçen haftalar boyunca bu karışık konuyu nasıl büyük bir kitlenin anlamasını sağlarım diye düşündüm. standart kitaplar adım adım yaklaşım izlerler. Ben de geçen iki  makalemde hemen hemen aynı yöntemi izledim. Bu yolu daha fazla takip etmemeye karar verdim çünkü  her okuyucunun kendi kodunu yazma noktasına gelmesi uzun zaman alacaktı. Bunun yerine başka bir   metodu   kullanmaya cüret ettim. Bunu "şok tedavi" olarak adlandırmaya karar verdim .Bu makale benim 3 boyutlu similasyonlarımdan bir tanesinin demosunun kodunu içerecek, ve ben bu kodu bit bit açıklamaya çalışacağım. Aslında standart OpenGL kitaplatında normal olarak işlenenleri detaylı biçimde açıklayacağım. Fakat inanıyorumki aniden sona atlamak ve okuyucuya kod örneklerini bazı ilginç şeylerle vermek kullanıcıların kodları denemesini ve bazı şeylerle uğraşmasını sağlar.Buna rağmen şimdilik okuyuculara herşeyin tam olarak nasıl çalıştığını anlatamayacağım. Umarım ki bu methot çalışır ve insanlar bu yöntemi daha hızlı ve daha doğru bulur.
 
  Geçtiğimiz 6 ay boyunca Pittsburg üniversitesinde jel ve polimer similasyonlarının geliştirilmesini destekleyen nesne yönelimli uygulma üzerinde çalıştım. Bu proje çoktan tamamıyla geliştirildi. Bilgisayar bilimlerinden pek çok insan için fizik ilginçtir , çünkü jel basit olarak polimerlerden oluşmuş bir sinir ağıdır. Ve sinir ağları için geliştirilmiş pek çok teknik jel yapılarına uygundur. Bu uygulamanın stripped down edilmiş birkaç objesini topladım ve ../../common/May1998/example2.tar.gz adı altında basit bir demo olarak paketledim. Bu paket Linux'ta diğer Unix'lerde veya GLUT kurulmuş Windows 95 / NT ' de derlenebilir. Bu demo (bağlanmış monomerlerden oluşan zincir ) hareket halindeki tek polimeri bazı ısılarda çözelti içinde asılı kalırken gösterir. The dynamics are tantalizing. It looks  like a snake on stimulants! It is very lively due to the collisions of solvent molecules. You will not see  the solvent, as it is taking care of through the equations of motion of the polymer.

                              Example2 polimer zinciri boyunca her düğümün (monomerin) koordinatlarını
                              izler animasyonun her karesinde monomerlerin koordinatlarında bir küre çizeriz ve sonra
                               monomerlerden monomerlere giden silindirleri kullanarak onları birleştiririz. Başlıca iki temel 3 boyutlu öğe var : Küre ve silindir. Herhangi bir molekülde monomerler arasındaki uzaklık zamanla değiştiğinden bütün bağlantıları sadece bir silindir kullanarak çözemeyiz, silindir o andaki iki monomer arası uzaklığa bağlı olarak tekrar ölçeklendirilmelidir.

         Soru1: 1 yüksekliğinde bir yatay silindir ve bir küre olmak üzere iki tane 3 boyutlu nesneye sahipsiniz. her iki nesnenin merkezi koordinatların orjininde olsun. Eğer polimerler hakkında bildiğiniz sadece düğümlerin x y z koordinatlarının sırası ise esas silindirin polimer bağlantılarını oluşturmak için nasıl ölçeklendirecek, döndürecek ve taşıyacaksınız?
 
        Anlayamadığım bir sebebten dolayı bilgisayarcılar kartezyen koordinatların anlamını belirginleştirmişler x: yatay y: düşey z: gözlemciye giden. Buna dikkat edin çünkü matematik veya bilim tabanınız varsa bu sizi karıştıracaktır. Animasyon penceresinin üst bölümünde o anki zamanı , polimerin o anki ısısını i ortalama ısısını , çözeltinin ısısını, friction of the solvent ve dış kameranın dönme açısını bilmenizi sağlayacak bir bilgilendirme banner 'ı var. Polimerin bütün yüzlerini tam olarak göstermek yerine kamera polimerin etrafında yavaşça döner.

         Gerçekten benim bu demo için seçtiğim polimer uzunluğu polimerin kendi dönmesini gerektirmeyecek kadar kısa example2.cxx dosyasındaki POLYMERLENGTH tanımını 2 ile 100 arasında değiştirebilirsiniz. Kameranın dönmesinin sebebi kullanıcının görüne bir problemi yani (koordinat sisteminin değişmesi) canlandırmasını istememdir. Ve hareket denkemlerinde kullanılan düğümlerin koordinatları kullanıcının bakış açısına bağlı değildir. (Genel kordinatlardadır)  Bu koordinatlar bilgisayar ekranının iki boyutlu x-y koordinatlarına dönüştürülmelidir. Görüş açısının her değiştiğinde polimer iç koordinatlarını iki boyutlu ekran koordinatlarına çeviren formüller değişir.

        Soru 2: Bu problemi nasıl çözersiniz? hareket denklemlerinin genel koordinatlardan iki boyutlu viewpoint koordinatlarına dönüştürülmesi çok fazla cebir gerektirdiğinden konumuzun dışındadır. Çünkü uygulanması çok zordur ve pek çok hata oluşabilir.
 
         İkinci sorunun cevabı çok basit sadece bir seçeneğimiz var : 3 boyutlu polimer modelinin genel koordinatlarda ifadesi ve bu koordinatların çerçevenin (frame) render edilmesi sırasında iki boyutlu görüş noktası (viewport) koordinatlarına çevrilmesi. Bu dönüşümü yapmak için OpenGL genelde donanım düzeyinde desteklenir .(OpenGL kartı olanlar farkı görebilirler) Ama OpenGL'in bu konuya nasıl yaklaştığını incelemeden önce isterseniz 3 boyutlu genel koordinatlardan  2 boyutlu pencere koordinatlarına geçişte kaç tane dönüşüm yapıldığına bakalım.

                                                                        Öncelikle Modelview koordinat dönüşümü gelir.
                                                                        Bu dönüşüm genel koordinatları gözlemcinin gözlerinin
                                                                        ( kamera ) yerine bağlı 3 boyutlu göz koordinatlarına
                                                                        dönüştürür. Bu dönüşümün Modelview olarak adlandırılmasının
                                                                        sebebi, bu dönüşümün benzer pekçok aralıklara uygulanabilmesidir.
                                                                        Modelleme ve görüntüleme uygulamalarından ikincisi bir
                                                                        photo-camera'nın bir stüdyoya yerlleştirilmesi ve tam
                                                                        karşıdaki görüntünün fotograf olarak adlandırılması, diğeri ise
                                                                        ilgilenilen objelerin kamera önüne yerleştirilmesi olarak
                                                                        düşünülebilir.

                                                                        Dönüşümün pipeline'ını takip edersek  göz koordinatlarının
                                                                        projeksiyon koordinat dönüşümlerine geçirildiğini görürüz.
                                                                        Bu dönüşümün amacı şimdilik gizli kalacak.
                                                                        Kameranın görüş yönünde  ve objelerin  görüş alanı içine
                                                                        yerleştirilmesinden sonra, OpenGL görünümün ne kadarının
                                                                        bilgisayar ekranına aktarılması gerektiğini bilmek
                                                                        isteyecektir. Orneğin, kamera çok uzaktaki bir dağa
                                                                        yönlendirilmiş olabilir. Bu durumda görüş alanı çok büyük bir
                                                                        alanı belirtecektir. Bilgisayarlar sadece sonlu şeyleri ele
                                                                        alabileceğinden görüntünün ne kadarını keseceğimizi
                                                                        belirtmek zorundayız. Bu dönüşüm aynı zamanda
                                                                        gizli yüzeylerin kaldırılmasıyla da ilgilenir. Sonda
                                                                        ulaşılacak koordinatlar Clip koordinatlarıdır. Hatırlarsınız
                                                                         ki, bu durum 3 boyutlu objelerin her zaman kamera önüne
                                                                        düşmesi için yeterli değildir. Fakat, projeksiyon dönüşümünü
                                                                        tanımlayan kesilmiş yüzeylerin içinde olmalıdır. Pekçok 3
                                                                        boyutlu persfektif özellikleri ( konik, ortagonal, ... ) bu
                                                                        aşamada uygulanabilir.

Şu an için ne persfektif böulünmenin ne de clip koordinatları ile normalleştirilmiş araç koordinatları arasındaki farkı incelemeye girişmeyeceğiz. Şimdilik bu gerekli değil.

Son önemli koordinat dönüşümü "Görüş noktası dönüşümü" . Burada,  bütün 3 boyutlu dönüşümlerden geçen 3 boyutlu koordinatlar son iş olarak bilgisayar ekranının 2 boyutlu yüzeyine işlenir.

Koordinat dönüşümleri matrislerle ( iki boyutlu sayı dizileri ile ) ifade edilir. Yukarıdaki her bir dönüşüm için ayrı bir matris kullanılır. Bu matrisler çerçeveyi render etmeden önce programın herhangi bir yerinde tanımlanabilirler. OpenGL her sahnenin başında birtakım matris dönüşümlerini uygular. Bu, çok akılcı ve yararlı bir tekniktir ve biz bunu daha ilerideki yazılarda inceleyeceğiz. Şu an için, gelin kodu inceleyelim ve bu dönüşümlerin nasıl ve nerede uygulandığını görelim. example2.cxx dosyasında tanıdık olduğunuz yeniden şekillendirme fonksiyonları var.

void mainReshape(int w,int h){

//VIEWPORT TRANSFORMATION
glViewport(0,0,w,h);

//PROJECTION TRANSFORMATION
glMatrixMode(GL_PROJECTION);
glLoad Identity();
glFrustum(wnLEFT,wnRIGHT,wnBOT,wnTOP,wnNEAR,wnFAR);

//MODELWIEW TRANSFORMATION
glMatrixMode(GL_MODELVIEW);

...............
glViewport(x,y,w,h) direktifi,görüntü alanının dönüşümünü sağlar : x ve y üçgeni gören pencerenin sol alt köşe
koordinatları ve 'w' ve 'h'  de görüş alanının boyutlarıdır.
Bütün numaralar pixel (parantezler) içinde verilir.
Ardından glMatrix Mode() ,son matrisi seçmek için kullanılır , planlanan dönüşümün belirlenmesine başlamak için
GL_PROJECTION parametresiyle çagırılır. Herhangi bir matris dönüşümü belirlenmeden önce (köşe koordinatlarını
etkilemeyen) birleşim matrisi yüklemek tavsiye edilir.Bu işlem son matrisi birleştirmeye başlayan glLoad Identity() ile
yapılır. Daha sonra sıra üç boyutlu perspektifin bildirimine gelir; glFrustum(sol,sağ,alt,üst,yakiı,uzak) cumlesi sağ,sol,alt,üst,yakın
ve uzak pozisyonlarda kesişen yüzeyleri bildirir.Bu numaralar göz koordinatlarında belirlenir ve sayıların büyüklükleri de görüntü
alanında (bilgisayar ekranı) yerleştirilen boşluk hacimlerinin şeklini (böylelikle perspektifini ) belirler. Bu belki karışık
görunebilir;benim alışmam da bir sure aldı. Hakkında bir alışkanlık kazanabilmek için yapılacak en iyi şey çesitli sayılar
denemektir; yalnız her zaman hatırlanması gereken şu ki; hangi sayıyı seçerseniz seçin model-viewed (örnek alınan) nesne
kesişen yüzeylerin içinde kalmalıdır. Aksi takdirde ekranda hiçbir şey görnmeyecektir. Planlanan dönüşümün belirlenmesi için
farklı yollar da var. Zaman içinde bu konulardan da bahsedeceğiz.
Final olarak geçerli matrisi (örnek alinan) modelview harf kalıbıyla degiştiririz. Bu iş için tekrar GL_MODELVIEW
parametresini kullanarak glMatrixMode() özelliğinden yararlanırız. mainReshape() özelliği diğer ilgisiz şeylerle devam eder ve
biter. Burada önemli olan şudur: Asıl pencere yeniden şekillendirilirken bu özellik, görüntü alanını ve planlanan dönüşümü
belirlendi. Son olarak da (örnek alınan) modelview matrisi geçerli duruma getirdi.
Bundan sonra, mainDisplay() özelliği modelview (örnek alınan) dönüşümün belirtilmesine son verir ve polimeri scene() ile
tamamlar:

void mainDisplay(){
glutSetWindow(winIdMain);

glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
//Renkleri netleştirir ve (derinlik verir) depth buffers
//Bu ,tahtayi silmek gibidir

//MODELVIEW DONUSUMUNE DEVAM: Kamerayı kur ve yerleştir
glLoadIdentitiy(); //Birleşimi geçerli matrise yükle
glTranslatef(0.0,0.0,-4.0); //Kamerayı 4 adım geri götür
//kamerayı -z yönünü gösterir şekilde bırakırız. Aslında bu, arkadaki görüntüyü -z yönünde
//4 adım hareket ettirerek gerçekleşir. Ekaranda yalnızca izlenen hacmin içinde kalan
//görüntü elemanları gözükür. (Daha sonra planlanan dönüsüm kısmına bakınız)

//Zinciri oluşturmak
glSaclef(0.5,0.5,0.5);
glRotatef(Aci,0,1,0);
scene();

glutSwapbuffers();
};

Umarım iki alt pencere kullanarak okuru çok şaşırtmamışımdır. Sonuçları alt pencerelere baglı olarak açıklamıyorum; çünkü
bu bir önceki bölümde (windows management) zaten ele alınmıştı. Eğer şüpheli olan bir kısım varsa lütfen geri dönüp hafızanızı
tazeleyiniz.
Bu özellik oldukça açık ve basittir. İlk önce glClear rengi siler ve (derinlik verir) depth buffers.Depth buffer (derinlik
verilmesi) simdi üç boyutta önemlidir; çünkü her köşenin z koordinati, saklı yüzeyleri ve yüzeylerin yer degiştirmesini saptamak
için test edilmelidir. Ardindan birleşim matrisi geçerli modelview matris üzerine yükleriz ve 3 modelling dönüşümü çagırırız:

glTranslate(xt,yt,zt),,bu geçerli koordinat sistemini (xt,yt,zt) vektörleriyle taşır. Bizim durumumuzda bu işlem kamerayı z'de
4 birim geri götürme etkisini yaratır ki bu da örnekten uzaktadır. Eğer bunu yapmasaydık kamera orjinde, sahnenin ortasında
kalacaktı ve çok az şey görebilecektik.
glScalef(xs,ys,zs),adından da anlaşılacağı gibi koordinat sistemlerini sırasıyla x,y,z eksenleri boyunca xs,ys,zs faktörleriyle
ölçülendirmeye yarar. Bu ölçülendirme koordinat sisteminin dünyada kabul görmüş koordinat sistemine uyması için gereklidir.
glRotatef(aci,vx,vy,vz), geçerli koordinat sistemini (vx,vy,vz) normal vektörü etrafında belli açılarla döndürür. Bu
bizim, kameranın döndügü izlenimini vermek için kullandıgımız bir hiledir. Aslında dönen sahnedir. Kamerayı hareket ettirmenin
başka birçok yolu olmasına rağmen şu anda en kolayı budur.

Son bir uyarı: Modelling dönüsümlerin sırası çok onemlidir. Her koordinat sistemi çagırışımızda Modelview matrise ne
olduğunu anlamamız gerekir. Her dönüşüm Ti matemaksel olarak bir Mi matrisiyle temsil edilir. Bir dizi dönüşümün superposition
i ,Tn Tn-1....T1 (örneğin: yer degiştirme+ölçülendirme+döndürme) matematiksel olarak bir tek matrisle temsil edilir.M=Mn
Mn-1.......M1
.Sıralama en can alıcı noktadır; çünkü karmaşık M dönüşümü bir köşeye uygulandıgında dönüşümler ters sırada gerçekleşir.
 

M v = Mn Mn-1 .... M1 v

Ilk olarakM1, sonraM2, vb... ve en son olarak da Mn Kod örneğimizde transformansyonları yandaki sıraya göre belirttim:
translasyon-> ölçeklendirme -> dönmüş. Bundan dolayı, dünya koordinatlarındakı modelimizin her noktası grafik ekranına
yansıtılmadan önce dönmüş -> ölçeklendirilmiş -> çevirilmis olmalıdır.

Kod yazarken, bu transformasyonların ters sırasını her zaman aklınızda bulundurun, aksi taktirde çok şaşırtıcı sonuçlar
bulabilirsiniz.

scene ?> fonksiyonu polimer obje uzerindeki 3D-çeviricisini çalıştırır. 3D modelinin sonradan nasıl inşa edildiğini anlamak için
Gd-OpenGL.cxx dosyasına gidip member fonksiyonu draw GdPolymer ? P ye bir göz atmak gerekir. Polimer zincirindeki bütün
parçalardan geçen bir ana halka vardır ; öyle ki bu halka X, Y, Z koordinatlarını tekrar bulup getirir ve o bölgede bir küre çizer
ve sonra birbirine halen baglı olan parçalardaki bağlar boyunca silindirler çizer. Soru 1'i hatırlıyor musunuz? İşte size bir olası
çözüm ... Daha hızlı bir çözüm üretebilirseniz bizim de haberimiz olsun.

Okuyucunun Polimer çevirme rutinini tamamiyle anlayabilmesi için bir şey daha var. glPushMatrix?> ve glPopMatrix?> ne işe
yarar ?

Polimer modelinde sadece 2 tane geometrik temel vardır ; biri merkezi orijinde olan 0.40 yarıçaplı bir küre, diğeri ise yüksekliği
1.0 yarıçapı
0.40 olan bir dogru silindir. Polimer, kureleri ve silindirleri düzgün bir pozisyonda yerleştirmek için bu iki temeli ve
transformasyonlar serisini kullanmak suretiyle yapılır. glCalList ?Parça> ve glCalList?Silindir> komutlarından her biri her işleme
konulduğunda orijinde yeni bir küre ve silindir çevirilmiş olur. Küreleri X, Y, Z koordinatlarına taşımak için bir translasyona
ihtiyacımız var ?bkz. glTranlatef?X, Y, Z>>; Bir silindiri bir ara zincir gibi çevirmek ve yerleştirmek daha zor olur çünkü ilk
başta silindiri ara zincir kadar büyük yapmanız lazım ve daha sonra onu doğru yöne çevirmeniz lazım. ?Benim hesap yöntemime
göre rotasyon transformasyon şeklinde bir derecelendirme kullanılır>

3D modelini inssa etmek için hangi metod kullanılırsa kullanılsın ona hiç şüphe yok ki o ek transformasyonlara, tranzlasyonlara
ve rotasyonlara ihtiyaç olacak. scene ?> fonksiyonu çağırıldığında OpenGL pozisyon makinasındaki mevcut matris
MODELVIEW matrisidir. Daha önce de belirttiğimiz gibi, bu, modelin dünya koordinatlarinin clipping koordinatlarına
projeksiyonunu temsil eden matristir. Bu ciddi bir sorundur ; modelview matrisi hala geçerli matris iken, 3D modelini
kurmak için uygulanan her ilave transformasyon geçerli matrise eklenecek ve modelview tranformasyonunu tahrip etme
şeklindeki arzulanmaz bir sonuca yol açacaktır. Bununla yapılan iki temel işlem vardır ; glPushMatrix?> ile uygulanan stack
push ve gl PopMatrix?> ile uygulanan pop. scene?> fonksiyonun kaynak kodunu bir kere daha inceleyiniz ve her parçanın
küresini tercume etmeden önce MODELVIEW matrisini stack'in içine göndermek için bir kereliğine push işlemini çağırdığımızda
dikkat ediniz. Halkanın sonunda da MODELVIEW matrisini geri getirmek için pop işlemini çağırınız. Polimer sıralarını çeviren
içeride bulunan halkanın kendi push'u ve pop operasyonları vardır ; öyle ki bunlar skalayi izole eder ve küre ile silindirleri
etkileyen tranzlasyonda transformasyonları çevirir.

3D tranformasyonlari matris stacklari hakkında söylenecek çok söz yok. Bu makalede biz sadece her iki konuyu yuzeysel bir
şekilde anlattık. Şu an için bu kadarlık bir anlatım yeterli olur, ilgilenen okuyucunun kaynak kodunu kendisi arastırması ve kendi
3D modellerini geliştirmesi gerekir. Kod Örneği 2'de daha önce arastırılmammış bazı çehreleri de kullanır: materyaller ve
ışıklandırma. Edisyonların tartışmasını daha sonraki bir makaleye bırakıyoruz. Bir dahaki sefere matris stacklerini ve 3D
tranformasyonlarını daha derin bir şekilde anlatacağız. Hareket eden bir robotu OpenGL komutlarıyla nasıl yönlendireceğimizi
de göstereceğiz. O zamana kadara OpenGL ile iyi vakiti geçirmeye bakın.


Daha Çok Bilgi İçin:
© 1998 Miguel Angel Sepulveda
Bu sanalyörenin bakımı Miguel A Sepulvedatarafından yapılmaktadır.