Skip to content

OpenGL Kullanarak Bezier Yüzeyinin Çizdirilmesi

Aşama aşama gidilirse bir Bezier Yüzeyi çizdirmek zor bir iş değil. Burada bunu yapmaya çalışacağız. Bir Bezier eğrisinden başlayıp, yüzeye doğru geçiş yapacağız.
Basit Bir Çizgi

Normalde formül kullanmadan OpenGL kütüphanelerini kullanarak:


glBegin(GL_LINES);

glVertex2f(-1,2);

glVertex2f(7,7);

glEnd();

çizgi çizebiliriz. Fakat aynı çizgi nokta kullanılarak basit bir geometri formülüyle şöyle çizdirilebilir:


GLfloat a,b,X,Y,Ax,Ay,Bx,By;
Ax = 1; Ay = 2; Bx = 7; By = 7;

glBegin(GL_POINTS);
for(a=0;a<=1;a+=0.01){

b = 1-a;
X = Ax*a + Bx*b;
Y = Ay*a + By*b;
glVertex2f(X,Y);

}
glEnd();

Burada basit olarak A(1,2) noktasından B(7,7) noktasına bir doğru çizdik.

Çizdirme işlemi yapılırken a’nın ve b’nin toplamının 1 olduğuna dikkat edin. Bunlar birbirini tamamlayan değerlerdir. Yüzey çizerken de bunları kullanacağız.

Çizgi çizdirme işlemini yaptıysanız kafanızda bir şeyler oluşmuş demektir.

Eğri Çizdirme

Eğri çizdirmek için kullanacağınız matematiksel formüller eğri ifade etmelidirler. Örneğin (a+b)² = a² + 2a·b + b² gibi bir ifadenin b = 1 için grafiğini çizmeye kalksanız u’ya benzeyen bir eğri grafiği elde edersiniz. Eğer (a+b)³ = a³ + 3·a²·b + 3·a·b² + b³ ifade kullanırsanız s’ye benzer bir grafik elde edersiniz. Eğer 3 kontrol noktalı Bezier eğrisi çizmek istiyorsanız 3 ifade topladığınız kare formülünü kullanırsınız. Eğer 4 kontrol noktası olan bir Bezier eğrisi çizmek istiyorsanız küp formülünü kullanmanız gereklidir. Kare aldığınıza bu yüzden kübik, küp aldığınıza da quadric bezier eğrisi denilmektedir. Şimdi quadric bir Bezier eğrisi çizmeyi deneyelim.

A(3,0), B(4,3), C(8,-4), D(9,0)  noktaları kontrol noktalarımız olsun.

 X(a) = Ax·a^3 + Bx·3·a^2·b + Cx·3·a·b^2 + Dx·b^3
 Y(a) = Ay·a^3 + By·3·a^2·b + Cy·3·a·b^2 + Dy·b^3
 Z(a) = Az·a^3 + Bz·3·a^2·b + Cz·3·a·b^2 + Dz·b^3

Bu üç boyutlu eğri formülüdür. Biz iki boyutlu bir eğri oluşturacağız, bu yüzden z kordinatlarını vermedim. Örnek
verdiğimiz noktaları kullanırsak:

 X(a) = 3·a^3 + 4·3·a^2·b + 8·3·a·b^2 + 9·b^3
 Y(a) = 0·a^3 + 3·3·a^2·b -4·3·a·b^2 + 0·b^3

formüllerini elde ederiz. Bunu OpenGL kullanarak yazalım:


double Ax = 3.0; double Ay = 0.0;
double Bx = 4.0; double By = 3.0;
double Cx = 8.0; double Cy = -4.0;
double Dx = 9.0; double Dy = 0.0;

double X;
double Y;

double a;
double b;

glBegin(GL_LINE_STRIP);

for( a = 0; a {
b = 1-a;

X = Ax*a*a*a + Bx*3*a*a*b + Cx*3*a*b*b + Dx*b*b*b;
Y = Ay*a*a*a + By*3*a*a*b + Cy*3*a*b*b + Dy*b*b*b;

glVertex2d(X, Y);

}

glEnd();

Aşağıdakine benzer bir şekil ortaya çıkacaktır.

Bezier Yüzeyi

Bezier Yüzeyi ise iki bezier eğrisinin çarpımından oluşmaktadır. Yani:
1. Bezier eğrisinden 4 nokta,
(a+b)^3 = a^3 + 3·a^2·b + 3·a·b^2 + b^3
2. Bezier eğrisinden 4 nokta olmak üzere,
(c+d)^3 = c^3 + 3·c^2·d + 3·c·d^2 + d^3
Çarpımları sonucu 16 noktalı Beizer Yüzeyi oluşur:

(a³ + 3·a²·b + 3·a·b² + b³)·(c³ + 3·c²·d + 3·c·d² + d³) =

a³·c³     + 3·a³·c²·d   + 3·a³·c·d²   + a³·d³
+ 3·a²·b·c³ + 9·a²·b·c²·d + 9·a²·b·c·d² + 3·a²·b·d³
+ 3·a·b²·c³ + 9·a·b²·c²·d + 9·a·b²·c·d² + 3·a·b²·d³
+ b³·c³     + 3·b³·c²·d   + 3·b³·c·d²   + b³·d³

Yukarıdaki formülasyon her eksen için uygulanmalıdır. Sonuçta:

X(a,c) = Ax·a³·c³       + Bx·3·a³·c²·d
+ Cx·3·a³·c·d²   + Dx·a³·d³
+ Ex·3·a²·b·c³   + Fx·9·a²·b·c²·d
+ Gx·9·a²·b·c·d² + Hx·3·a²·b·d³
+ Ix·3·a·b²·c³   + Jx·9·a·b²·c²·d
+ Kx·9·a·b²·c·d² + Lx·3·a·b²·d³
+ Mx·b³·c³       + Nx·3·b³·c²·d
+ Ox·3·b³·c·d²   + Px·b³·d³

Y(a,c) = Ay·a³·c³       + By·3·a³·c²·d
+ Cy·3·a³·c·d²   + Dy·a³·d³
+ Ey·3·a²·b·c³   + Fy·9·a²·b·c²·d
+ Gy·9·a²·b·c·d² + Hy·3·a²·b·d³
+ Iy·3·a·b²·c³   + Jy·9·a·b²·c²·d
+ Ky·9·a·b²·c·d² + Ly·3·a·b²·d³
+ My·b³·c³       + Ny·3·b³·c²·d
+ Oy·3·b³·c·d²   + Py·b³·d³

Z(a,c) = Az·a³·c³       + Bz·3·a³·c²·d
+ Cz·3·a³·c·d²   + Dz·a³·d³
+ Ez·3·a²·b·c³   + Fz·9·a²·b·c²·d
+ Gz·9·a²·b·c·d² + Hz·3·a²·b·d³
+ Iz·3·a·b²·c³   + Jz·9·a·b²·c²·d
+ Kz·9·a·b²·c·d² + Lz·3·a·b²·d³
+ Mz·b³·c³       + Nz·3·b³·c²·d
+ Oz·3·b³·c·d²   + Pz·b³·d³

Şeklinde bir sonuç elde edilir. Örnek verecek olursak:
A(2,0,1), B(3,2,-1), C(6,2,1), D(9,0,-1), E(0,3,1), F(3,4,-1), G(6,4,1), H(10,3,-1), I(0,5,1), J(3,6,-1),
K(6,6,1), L(10,5,-1), M(1,9,1), N(3,8,-1), O(6,8,1),P(7,9,-1)
Öncelikle yukarıda a ve c değişkenli fonksiyonları yazdık fakat yüzeydeki noktaların doğrultularını belirlemek için bu noktaların
normaline ihtiyacımız var bunu da dört aşamada elde edeceğiz.

A değişkenine göre türev alıyoruz. B’ye göre almaya gerek yok zaten b’nin 1-a olduğunu biliyoruz.
XDA a’ya göre türev alınmış X(a,c) demektir.

XDA(a,c) = Ax·3·a²·c³             + Bx·9·a²·c²·d
+ Cx·9·a²·c·d²           + Dx·3·a²·d³
+ Ex·3·(2·a-3·a²)·c³     + Fx·9·(2·a-3·a²)·c²·d
+ Gx·9·(2·a-3·a²)·c·d²   + Hx·3·(2·a-3·a²)·d³
+ Ix·3·(1-4·a+3·a²)·c³   + Jx·9·(1-4·a+3·a²)·c²·d
+ Kx·9·(1-4·a+3·a²)·c·d² + Lx·3·(1-4·a+3·a²)·d³
+ Mx·3·(2·a-1-a²)·c³     + Nx·9·(2·a-1-a²)·c²·d
+ Ox·9·(2·a-1-a²)·c·d²   + Px·3·(2·a-1-a²)·d³

YDA(a,c) = Ay·3·a²·c³             + By·9·a²·c²·d
+ Cy·9·a²·c·d²           + Dy·3·a²·d³
+ Ey·3·(2·a-3·a²)·c³     + Fy·9·(2·a-3·a²)·c²·d
+ Gy·9·(2·a-3·a²)·c·d²   + Hy·3·(2·a-3·a²)·d³
+ Iy·3·(1-4·a+3·a²)·c³   + Jy·9·(1-4·a+3·a²)·c²·d
+ Ky·9·(1-4·a+3·a²)·c·d² + Ly·3·(1-4·a+3·a²)·d³
+ My·3·(2·a-1-a²)·c³     + Ny·9·(2·a-1-a²)·c²·d
+ Oy·9·(2·a-1-a²)·c·d²   + Py·3·(2·a-1-a²)·d³

ZDA(a,c) = Az·3·a²·c³             + Bz·9·a²·c²·d
+ Cz·9·a²·c·d²           + Dz·3·a²·d³
+ Ez·3·(2·a-3·a²)·c³     + Fz·9·(2·a-3·a²)·c²·d
+ Gz·9·(2·a-3·a²)·c·d²   + Hz·3·(2·a-3·a²)·d³
+ Iz·3·(1-4·a+3·a²)·c³   + Jz·9·(1-4·a+3·a²)·c²·d
+ Kz·9·(1-4·a+3·a²)·c·d² + Lz·3·(1-4·a+3·a²)·d³
+ Mz·3·(2·a-1-a²)·c³     + Nz·9·(2·a-1-a²)·c²·d
+ Oz·9·(2·a-1-a²)·c·d²   + Pz·3·(2·a-1-a²)·d³

Daha sonra c’ye göre türev alıyoruz.

XDC(a,c) = Ax·3·a³·c²             + Bx·3·a³·(2·c-3·c²)
+ Cx·3·a³·(1-4·c+3·c²)   + Dx·3·a³·(-1+2·c-c²)
+ Ex·9·a²·b·c²           + Fx·9·a²·b·(2·c-3·c²)
+ Gx·9·a²·b·(1-4·c+3·c²) + Hx·9·a²·b·(-1+2·c-c²)
+ Ix·9·a·b²·c²           + Jx·9·a·b²·(2·c-3·c²)
+ Kx·9·a·b²·(1-4·c+3·c²) + Lx·9·a·b²·(-1+2·c-c²)
+ Mx·3·b³·c²             + Nx·3·b³·(2·c-3·c²)
+ Ox·3·b³·(1-4·c+3·c²)   + Px·3·b³·(-1+2·c-c²)

YDC(a,c) = Ay·3·a³·c²             + By·3·a³·(2·c-3·c²)
+ Cy·3·a³·(1-4·c+3·c²)   + Dy·3·a³·(-1+2·c-c²)
+ Ey·9·a²·b·c²           + Fy·9·a²·b·(2·c-3·c²)
+ Gy·9·a²·b·(1-4·c+3·c²) + Hy·9·a²·b·(-1+2·c-c²)
+ Iy·9·a·b²·c²           + Jy·9·a·b²·(2·c-3·c²)
+ Ky·9·a·b²·(1-4·c+3·c²) + Ly·9·a·b²·(-1+2·c-c²)
+ My·3·b³·c²             + Ny·3·b³·(2·c-3·c²)
+ Oy·3·b³·(1-4·c+3·c²)   + Py·3·b³·(-1+2·c-c²)

ZDC(a,c) = Az·3·a³·c²             + Bz·3·a³·(2·c-3·c²)
+ Cz·3·a³·(1-4·c+3·c²)   + Dz·3·a³·(-1+2·c-c²)
+ Ez·9·a²·b·c²           + Fz·9·a²·b·(2·c-3·c²)
+ Gz·9·a²·b·(1-4·c+3·c²) + Hz·9·a²·b·(-1+2·c-c²)
+ Iz·9·a·b²·c²           + Jz·9·a·b²·(2·c-3·c²)
+ Kz·9·a·b²·(1-4·c+3·c²) + Lz·9·a·b²·(-1+2·c-c²)
+ Mz·3·b³·c²             + Nz·3·b³·(2·c-3·c²)
+ Oz·3·b³·(1-4·c+3·c²)   + Pz·3·b³·(-1+2·c-c²)

Normal vektörleri bulmak için:
Nx = (YDA·ZDC)-(YDC·ZDA)
Ny = -((XDA·ZDC)-(XDC·ZDA))
Nz =(XDA·YDC)-(XDC·YDA)
Formüllerini kullanabiliriz. Burada bulduğumuz vektör Normalize edilmemiş vektördür. Normalize
etmek için vektörlerin uzunluğu bulunur ve bu uzunluğa vektörler bölünür.
L = sqrt(Nx2+Ny2+Nz2)
Nx’= Nx/L
Ny’= Ny/L
Nz’= Nz/L
Bu vektörler X(a,c), Y(a,c) ve Z(a,c) vektörleriyle birlikte istediğimiz yüzeyi bize verirler.
Örneğimizdeki Bezier Yüzeyinin, 4 noktasını hesaplayıp, o noktaları birleştirerek detayı az olan bir
yüzey elde etmiş olacağız. Bezier yüzeyinin üzerindeki x ve y noktaları yaklaşık olarak aşağıdaki
gibidir. İki boyut için gerekli noktaları almak bile bize bezier yüzeyi hakkında bilgi verecektir.
VA = (2.0,0.0),VB = (3.6,1.3),VC = (6.07,1.33),VD = (9.0,0.0),VE = (0.6,2.7), VF = (3.2,3.6), VG = (6.2,3.6), VH = (9.6,2.7), VI = (0.3,5.5), VJ = (3.1,5.85), VK= (6.0,5.86), VL = (9.07,5.5), VM = (1.9,9.0), VN = (3.2,8.33), VO = (5.4,8.33), VP = (6.9,8.9)

OpenGL kodu çok uzun olacağı için burada paylaşmıyorum, şuradan indirip inceleyebilirsiniz.

2 Comments

  1. Mahmut Mahmut

    Faydalı bir çalışma olmuş. Teşekkürler.

Bir Cevap Yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir