Sunday, February 26, 2012

OpenGL'de Doğruları Kullanarak Ekrana Harf Yazdırmak

Herkese merhaba, bugünkü yazımda Java üzerinde OpenGL programlamaya giriş yapmayı planlıyorum. Basit bir program yazıp, bu programı çok fazla detaya girmeden açıklayacağım. Programımız OpenGL içinde hazır bulunan "glVertex2f" fonksiyonunu kullanarak ismimizin baş harfini ekrana yazdıracak. Bu programın amacı, hem OpenGL'deki koordinat sistemini kavramak hem de "glVertex2f" fonksiyonunun kullanımını görmek ve anlamak. Yazıyı daha fazla uzatmadan kodumuzu veriyorum.

package Package;

import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;

import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.awt.GLJPanel;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.Timer;

//Run this as a Java application 
public class Test extends JPanel implements GLEventListener, KeyListener {

 private static final long serialVersionUID = 1L;
 private int updatePeriodInMilliseconds = 10;

 public static void main(String[] args) {
  JFrame window = new JFrame("Basic JOGL App 2D");
  window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  Test Test = new Test();
  window.setContentPane(Test);
  window.pack();
  window.setVisible(true);
  window.addKeyListener(Test);
 }

 public Test() {
  final GLJPanel drawable = new GLJPanel();
  drawable.setPreferredSize(new Dimension(400, 400));
  drawable.addGLEventListener(this);
  setLayout(new BorderLayout());
  add(drawable, BorderLayout.CENTER);

  Timer timer = new Timer(updatePeriodInMilliseconds, new ActionListener() {
   @Override
   public void actionPerformed(ActionEvent evt) {
    updateScene();
    drawable.repaint();
   }
  });
  timer.start();
 }

 protected void updateScene() {
 }

 @Override
 public void init(GLAutoDrawable drawable) {
  GL2 gl2 = drawable.getGL().getGL2();
  gl2.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
 }

 @Override
 public void display(GLAutoDrawable drawable) {

  GL2 gl2 = drawable.getGL().getGL2();
  gl2.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
  gl2.glColor3f(0.0f, 0.0f, 1.0f);

  gl2.glBegin(GL2.GL_LINES); 
  gl2.glVertex2f(-.9f, .9f);
  gl2.glVertex2f( .9f, .9f);
  gl2.glVertex2f( .0f, .9f);
  gl2.glVertex2f( .0f,-.9f);
  gl2.glEnd();

 }

 @Override
 public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
  System.out.println("window size was changed");
 }
 
 public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
 }

 @Override
 public void dispose(GLAutoDrawable drawable) {
 }

 @Override
 public void keyPressed(KeyEvent arg0) {
  switch(arg0.getKeyCode()) {
   case KeyEvent.VK_ESCAPE:
    System.out.println("Escape was pressed");
    System.exit(0);
    break;
  }
 }

 @Override
 public void keyReleased(KeyEvent arg0) {
 }

 @Override
 public void keyTyped(KeyEvent arg0) { 
 }
}
Kodumuzu JAVA programlama dilini kullanarak yazdım. Eclipse üzerinde OpenGL kurulumu ve proje oluşturma hakkında yeterli bilgiye sahip değilseniz, bu linkteki yazımı okuyup gerekli işlemleri rahatça yapabilirsiniz.

İlk olarak "main" fonksiyonumuzu açıklayalım. Bu fonksiyonumuzun içinde ÖZETLE, JFrame sınıfından "window", Test sınıfından ise "test" adlarında 2 tane yeni obje oluşturuyoruz. "test" objemizi, "window" objemizin içine atıp, "window" objemizi "setVisible" metodu ile görülebilir hale getiriyoruz.
public static void main(String[] args) {
 JFrame window = new JFrame("Basic JOGL App 2D");
 window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
 Test Test = new Test();
 window.setContentPane(Test);
 window.pack();
 window.setVisible(true);
 window.addKeyListener(Test);
}
Aşağıdaki kod parçacığı ise, bizim oluşturduğumuz "Test" sınıfına ait constructor. Burada yaptığımız işlem ise ÖZETLE "GLJPanel" sınıfından oluşturduğumuz bir objenin boyutunu, update işlemlerini ayarlamaktan ibaret. Bu şimdilik size bir şey ifade etmiyorsa pek telaşlanmayın. Çünkü bunlar zamanla aşinalık kazanacağınız şeyler.
public Test() {
 final GLJPanel drawable = new GLJPanel();
 drawable.setPreferredSize(new Dimension(400, 400));
 drawable.addGLEventListener(this);
 setLayout(new BorderLayout());
 add(drawable, BorderLayout.CENTER);

 Timer timer = new Timer(updatePeriodInMilliseconds, new ActionListener() {
  @Override
  public void actionPerformed(ActionEvent evt) {
   updateScene();
   drawable.repaint();
  }
 });
 timer.start();
}
Aşağıdaki "init" fonksiyonu ise, OpenGL kodlarımızı görüntüleyeceğimiz ekranı, istediğimiz renklerle temizleme, programımızdaki çeşitli değişkenlere, ilk değer ataması yaptığımız yerdir. "gl2.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);" satırı ekranımızı beyaza boyamaktadır. OpenGL'deki renk kodları ile ilgili ilerleyen zamanlarda daha detaylı bir yazı yazacağım.
@Override
public void init(GLAutoDrawable drawable) {
 GL2 gl2 = drawable.getGL().getGL2();
 gl2.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
}
Şimdi sıra geldi, ismimizin baş harfini ekranımıza yazdırmaya. Aşağıdaki fonksiyon tam olarak bu işlemi yapmaktadır. Ve bu fonksiyonu anlamak programı anlamak için yeterlidir.
@Override
public void display(GLAutoDrawable drawable) {

 GL2 gl2 = drawable.getGL().getGL2();
 gl2.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
 gl2.glColor3f(0.0f, 0.0f, 1.0f);

 gl2.glBegin(GL2.GL_LINES); 
 gl2.glVertex2f(-.9f, .9f);
 gl2.glVertex2f( .9f, .9f);
 gl2.glVertex2f( .0f, .9f);
 gl2.glVertex2f( .0f,-.9f);
 gl2.glEnd();

}
Kısaca açıklamak gerekirse, "gl2.glColor3f(0.0f, 0.0f, 1.0f);" satırı, ekrana çizdireceğimiz, doğru, üçgen nokta v.s. gibi şeylerin hangi renk olacağını belirliyor. "gl2.glBegin(GL2.GL_LINES);" satırı ile çizdireceğimiz şeyin, ne olduğunu belirliyoruz. "GL2.GL_LINES" parametresi ile çizdirilecek şeyin doğrular kümesi olduğunu anlıyoruz.
gl2.glVertex2f(-.9f, .9f);
gl2.glVertex2f( .9f, .9f);
gl2.glVertex2f( .0f, .9f);
gl2.glVertex2f( .0f,-.9f);
Yukarıdaki kod parçacığı ise toplam 4 noktadan oluşan 2 doğru üretmektedir. İlk noktamızın x'i -.9f, y'si .9f, ikinci noktamızın x'i .9f, y'si .9f, üçüncü noktamızın x'i .0f, y'si .9f, dördüncü noktamızın x'i .0f, y'si -.9f'dir. İlk 2 nokta kendi arasında yatay bir doğru oluştururken, son iki nokta ise yine kendi arasında dikey bir doğru oluşturmaktadır. Son olarak açıklamak istediğim başka bir fonksiyon daha var. Aşağıdaki fonksiyon ise, program ile kullanıcı arasındaki etkileşimi sağlayan, klavyeden gelen komutları algılayan fonksiyondur. ÖZETLE yaptığı iş, eğer kullanıcı "ESC" tuşuna basarsa programı sonlandırmaktır.
@Override
public void keyPressed(KeyEvent arg0) {
 switch(arg0.getKeyCode()) {
  case KeyEvent.VK_ESCAPE:
   System.out.println("Escape was pressed");
   System.exit(0);
   break;
 }
}
Programı Ctrl+F11'e basıp derleyince aşağıdaki gibi bir resimle karşılaşacaksınız. Ben kendi ismimin baş harfi olan "T" harfini ekrana bastırdım. Siz bir adım daha ileri giderek kendi isminizi ekrana yazdırabilirsiniz. Bugünlük bu kadar, herkese iyi günler.

No comments:

Post a Comment