Carlos Calzada Grau Yazar hakkında: Bilgisayar bilimlerinde eğitim almış ve ilk Spectrum'dan beri bilgisayar grafikleriyle ilgili. Onun gelişme amacının micro$oft'a ihtiyaç duymamak olmasından dolayı Linux'dan çok zevk alıyorum. Benim diğer ekrandan bağımsız hobilerim bonsai'ler ve aquaria. İçerik: |
Özet:
Bu Renderman (I II ) hakkındaki serinin üçüncü makalesi, bu kez en önemli konulardan birini tartışacağız: "C" ve "C++" kullanarak bir sahneyi biçimlendirme ve hareketlendirme imkanı.
Önceki iki makaleden anlaşılacağı gibi, bir yazı dosyası yazarak doğrudan bir sahne yazma imkanı olmasına rağmen, bu çok sıkıcı bir iştir. Örneğin, sıçrayan bir topun hareketini anlatmak için bir".rib" dosyası yazmayı göz önünde bulundurun! Hayatlarımızı daha kolaylaştırmak için "C" veya "C++" uygulamaları yazma imkanımız var. Bu uygulamalar, sahne ve hareketi, ".rib" kod yazısını standart çıkışa gönderen kullanıcının tanımladığı fonksiyonlarda biçimlendirir. UNIX boruları bize sonra oluşturulmuş Renderman buyruklarını doğrudan başka bir yönteme (rendrib, rendribv, rgl gibi) veya ".rib" dosyasına göndermemize izin verir.
Blue Moon Rendering Tools 'u önceki yüklememiz lib ve include adlı iki dizin yarattı. Bunlar dört dosya içerir ki şimdi sadece ikisiyle ilgileneceğiz: ri.h bir başlık dosyası ve librout.a de fonksiyon kütüphanesi. Başlık dosyası /usr/local/include 'a ve libribout.a de /usr/local/lib 'a kopyalanmalıdır( Tecrübeli okuyucular onları farklı bir adrese yüklemeyi seçmeliler). Kütüphanenin yüklnemesinden sonra şimdi ilk örnek programımızı yazmaya hazırız.
İlk örneğimiz Renderman programcılığının temelini gösteriyor. Her C kodunda olduğu gibi, kütüphaneleri kullanmadan önce yugun gelen başlık dosyalarını yerleştirmeliyiz ki bizim durumumuzda bu ri.h'dır. Ayrıca programımzı kütüphaneyle bağlamalıyız, şöyle ki:
gcc myprogram.c -o myprogram -lribout -lm
İşte konsolda yazarak zaman kazandıran bir Makefile örneği:
LIBS = -lm -lribout PROGNAME = primero all: $(PROGNAME) $(PROGNAME).o: $(PROGNAME).c gcc -c $(PROGNAME).c $(PROGNAME): $(PROGNAME).o gcc -o $(PROGNAME) $(PROGNAME).o $(LIBS) |
İlk örneğimiz birkaç koordinat ekseni ve merkezde bir top yarattı, biz onu primero.colarak adlandıracağız, işte kaynak kodu:
1 #include <stdio.h> 2 #include <math.h> 3 #include <ri.h> 4 5 void main(void) 6 { 7 int i; 8 int x,y,z; 9 int nf; 10 float slopex,slopey,slopez; 11 12 RtColor Rojo={1,0,0}; 13 RtColor Verde={0,1,0}; 14 RtColor Azul={0,0,1}; 15 RtColor Blanco={1,1,1}; 16 17 RtPoint p1={30,0,10}; /* Posicicion inicial de la pelota */ 18 RtPoint p2={0,20,10}; /* Posicion final de la pelota */ 19 20 RtPoint from={0,100,100}; /* Direccion de la luz */ 21 RtPoint to={0,0,0}; 22 23 char name[]="primero.tif"; 24 RtFloat fov=45; 25 RtFloat intensity1=0.1; 26 RtFloat intensity2=1.5; 27 RtInt init=0,end=1; 28 29 RiBegin(RI_NULL); 30 RiFormat(320,240,1); 31 RiPixelSamples(2,2); 32 RiShutter(0,1); 33 RiFrameBegin(1); 34 RiDisplay(name,"file","rgb",RI_NULL); 35 name[7]++; 36 RiProjection("perspective","fov",&fov,RI_NULL); 37 RiTranslate(0,-5,60); 38 RiRotate(-120,1,0,0); 39 RiRotate(25,0,0,1); 40 RiWorldBegin(); 41 RiLightSource("ambientlight","intensity",&intensity1,RI_NULL); 42 RiLightSource("distantlight","intensity",&intensity2,"from",from,"to",to,RI_NULL); 43 RiColor(Azul); 44 RiTransformBegin(); 45 RiCylinder(1,0,20,360,RI_NULL); 46 RiTranslate(0,0,20); 47 RiCone(2,2,360,RI_NULL); 48 RiTransformEnd(); 49 RiColor(Verde); 50 RiTransformBegin(); 51 RiRotate(-90,1,0,0); 52 RiCylinder(1,0,20,360,RI_NULL); 53 RiTranslate(0,0,20); 54 RiCone(2,2,360,RI_NULL); 55 RiTransformEnd(); 56 RiColor(Rojo); 57 RiTransformBegin(); 58 RiRotate(90,0,1,0); 59 RiCylinder(1,0,20,360,RI_NULL); 60 RiTranslate(0,0,20); 61 RiCone(2,2,360,RI_NULL); 62 RiTransformEnd(); 63 RiColor(Blanco); 64 RiSphere(5,-5,5,360,RI_NULL); 65 RiWorldEnd(); 66 RiFrameEnd(); 67 RiEnd(); 68 }; |
İlk üç satır temel include dosyalarıdır. İçlerinden ri.h Renderman kütüphnaesi için protoyip başlıktır. Her Renderman çağırımı kendisine eşit ri.h'ın içinde C tarzında çağırıma sahiptir. , TransformBegin RiTransformBegin() fonksiyonuna uygun gelir, vb. make'i çalıştırarak çalışabilir primero'yu yaratın. Örneğimiz, yeni gönderimle (primero > primero.rib) veya çıkışı doğrudan başka bir işleme (primero | rendrib) gönderecek bir giriş dosyası yaratmak için çalıştırılabilir. Bu son durumda, rendrib görüntülenmiş bir dosyanın primero.tif'in oluşturulmasının görevini alır.:
Kütüphaneden fonksiyon çağırımları bir RiBegin(RI_NULL) ve bir RiEnd() çağırımları arasında özetlenmelidir. RiBegin'e geçen parametre tipik olarak RI_NULL 'dur. RIB'in çıkışını standart çıkışa ömnlemek için the standard output we could pass the name of the output filename * ("myfile.rib") or even the name of a process (like rendrib) the executable will then pass the renderman commands to the renderer without creating an intermediate RIB file.
Bizim örneğimizin kaynak kodu Renderman arayüzüne uygulanmış tipik C fonksiyonları ve talimatlarına sahiptir: RtColor tipi kırmızı, yeşil ve mavi değerleri (0.0 dan 1.0 değişen) üç tane reel sayı değerlerine sahip bir vektördür, sonra RtPoint boşlukta bir yerleşimi tutar ve RtFloat ve RtInt sırasıyla gerçel sayı ve tamsayıdırlar.
Satır 29 RiBegin(RI_NULL)'a bir çağırım içerir ki biz daha önce bahsetmiştik, Renderman arayüzü için bir başlangıç çağırımıdır. Bundan sonra aşağıdaki kullanışlı buyruk fonksiyonları tipik bir RIB dosyası olarak yazıldı. Kodu çalıştırmayı deneyin ve çıkışı bir dosyaya (./primero > primero.rib), gönderin. Çıkış şöyle olacaktır:
##RenderMan RIB-Structure 1.0 version 3.03 Format 320 240 1 PixelSamples 2 2 Shutter 0 1 FrameBegin 1 Display "camara.tif" "file" "rgb" Projection "perspective" "fov" [45 ] Translate 0 -5 60 Rotate -120 1 0 0 Rotate 25 0 0 1 WorldBegin LightSource "ambientlight" 1 "intensity" [0.1 ] LightSource "distantlight" 2 "intensity" [1.5 ] "from" [0 100 100] "to" [0 0 0] Color [0 0 1] TransformBegin Cylinder 1 0 20 360 Translate 0 0 20 Cone 2 2 360 TransformEnd Color [0 1 0] TransformBegin Rotate -90 1 0 0 Cylinder 1 0 20 360 Translate 0 0 20 Cone 2 2 360 TransformEnd Color [1 0 0] TransformBegin Rotate 90 0 1 0 Cylinder 1 0 20 360 Translate 0 0 20 Cone 2 2 360 TransformEnd Color [1 1 1] Sphere 5 -5 5 360 WorldEnd FrameEnd |
İlk örneğimiz çok kullanışlı değildi. Farklı bir sahne yaratmaak için benzer işlemleri yerine getiren yeni bir program yazmalıyız. Kütüphenelerin gücü gerçekte canlandırımların yapımındadır. İlk örneğimizde sadece bir çerçeve yapılmıştı, şimdi topun hareketini yapacağız.
İkinci örneğimizde sahnemiz yine üç koordiant ekseninde ve bir toptan meydana gelecek, fakat top bu sefer (30,0,10)'dan (0,20,10)'a hareket edecek ki bu bilgisayar ekranında sağdan sola harekettir. Her iki yer de RtPoint yapıları (satır 18 ve 19) kullanılarak tanımlanacaktır. Canlandırım için frames veya resimlerin sayısı nf değişkeninde tanımlanır. Bu numarayı ve baştakini ve final yerleşimlerinin birini kullanarak frame vasıtasıyla adımları üç yönde (slopex, slopey ve slopez) hesaplanabilir. Bütün bu bilgilere frame numarasını bir fonksiyonu gibi topun pozısyonunu nitelerken ihtiyaç duyacağız. 75'den 782e kadar ki satırlardaki TransformBegin/TransformEnd topun yerinin tanımlanmasına dikat eder. Her yeni yerleşim kolayca satır76'da hesaplanır.
1 #include <stdio.h> 2 #include <math.h> 3 #include <ri.h> 4 #include "filename.h" 5 6 void main(void) 7 { 8 int i; 9 int x,y,z; 10 int nf; 11 float slopex,slopey,slopez; 12 13 RtColor Rojo={1,0,0}; 14 RtColor Verde={0,1,0}; 15 RtColor Azul={0,0,1}; 16 RtColor Blanco={1,1,1}; 17 18 RtPoint p1={30,0,10}; /* Posicicion inicial de la pelota */ 19 RtPoint p2={0,20,10}; /* Posicion final de la pelota */ 20 21 RtPoint from={0,100,100}; /* Direccion de la luz */ 22 RtPoint to={0,0,0}; 23 24 char base[]="camara_"; 25 char ext[]="tif"; 26 char name[50]; 27 RtFloat fov=45; 28 RtFloat intensity1=0.1; 29 RtFloat intensity2=1.5; 30 RtInt init=0,end=1; 31 32 nf=100; /* Numero de frames */ 33 slopex=(p2[0]-p1[0])/nf; 34 slopey=(p2[1]-p1[1])/nf; 35 slopez=(p2[2]-p1[2])/nf; 36 37 RiBegin(RI_NULL); 38 RiFormat(320,240,1); 39 RiPixelSamples(2,2); 40 RiShutter(0,1); 41 for (i=1;i <= nf;i++) 42 { 43 RiFrameBegin(i); 44 filename(base,ext,sizeof(base)+4,i-1,name); 45 RiDisplay(name,"file","rgb",RI_NULL); 46 name[7]++; 47 RiProjection("perspective","fov",&fov,RI_NULL); 48 RiTranslate(0,-5,60); 49 RiRotate(-120,1,0,0); 50 RiRotate(25,0,0,1); 51 RiWorldBegin(); 52 RiLightSource("ambientlight","intensity",&intensity1,RI_NULL); 53 RiLightSource("distantlight","intensity",&intensity2,"from",from,"to",to,RI_NULL); 54 RiColor(Azul); 55 RiTransformBegin(); 56 RiCylinder(1,0,20,360,RI_NULL); 57 RiTranslate(0,0,20); 58 RiCone(2,2,360,RI_NULL); 59 RiTransformEnd(); 60 RiColor(Verde); 61 RiTransformBegin(); 62 RiRotate(-90,1,0,0); 63 RiCylinder(1,0,20,360,RI_NULL); 64 RiTranslate(0,0,20); 65 RiCone(2,2,360,RI_NULL); 66 RiTransformEnd(); 67 RiColor(Rojo); 68 RiTransformBegin(); 69 RiRotate(90,0,1,0); 70 RiCylinder(1,0,20,360,RI_NULL); 71 RiTranslate(0,0,20); 72 RiCone(2,2,360,RI_NULL); 73 RiTransformEnd> |
Şimdi ikinci örneğimizi deneyelim: derleyelim ve örneğin çıkışı rendribv'e göndererek çalıştıralım. Bu bizim canlandırımımızı çabucak görmemizi sağlayan kolay bir yöntemdir. rib çıkış dosyasını sınamak için sadece standart çkkışı yeni bir dosyaya gönderin. Okuyucu kontrol edebilir ki her sahne 100 kere (her çerçevede) tekrar ettiğinden yaratılmış dosya gerçekten büyüktür (segundo.rib 70kb'a karşılık gelir.)
Aşağıdaki şekil canlandırımdaki orta düzeydeki bir kaç çerçeveyi gösterir:
Tabi ki istediğimiz her nesneyi canlandırabiliriz: nesnelerin yerleşimleri, boyutları, ışığın yoğunluğu, kamera, nesneleri görünür ve görünmez yapma, vb.
Son örnekte tabandan sıçrayan topun nasıl yapılacağını görelim. İlk önce rebote() (sıçrama anlamında) fonksiyonunu tanımlarız ki bu fonksiyon üç parametre alır: şu naki çerçeve numarası, her sıçramadaki toplam çerçeve sayısı ve topun varacağı en fazla yükseklik. İşte kullanımı
float rebote (int i, int nframes, int max) { float min, z; while (i > nframes) i-=nframes; min=sqrt(max); z=i-((float)nframes/2.0); z=(z*min)/((float)nframes/2.0); z=(float)max - (z*z); return(z); } |
Birkaç kolay hesaplamalardan biri tipik parabola eğrisini (y=x^2) çerçeveler'in sayısı istenen en fazla yükseklikle çizimini yapmaktır. Aşağıdaki şekiller tercero.c programıyla her sıçramada yaratılmış birkaç orta düzey resimleri gösterir. :
Canlandırımları göz önüne getirerek birkaç canlandırılmış GIG dosyalarını uyguluyorum, xanim'le yavaş çalışmalarına (en azından Netscape altında) rağmen onları kabul adilebilir bir hızda görebiliriz.
Rectilinear hareket: segundo_anim.gif
Parabolik Hareket: tercero_anim.gif
Bu son örnek Renderman ve onun programcılığına C arayüzünün temellerinin sunumunun sonudur. En gelişmiş ve görülmeye değer programlama konusu gölgeleme başlığıdır. Onlar, sahnenin final görüntüsünü sahne dokuları, aydınlatmaları, vb. kontrol etmeye izin verirse, kontrol eder.
Yazının Türkçeye gönderilen aslı
İspanyolcadır.
Miguel A Sepulveda tarafından gözden geçirilip
düzenlenmiştir.
Webpages maintained by the LinuxFocus Editor team
© Carlos Calzada Grau LinuxFocus 1999 |