Bir nesnenin çevresini algılayıp anlamlandırması, oyun geliştirme ve simülasyon dünyasında kritik bir konudur. Bu çevresel veriler kullanılarak dinamik ışıklandırma, gölge efektleri, yapay zeka karar mekanizmaları ve daha birçok oyun mekaniği inşa edilebilir. Örneğin, bir odadaki ışığın yan odaya sızıp sızmadığını belirlemek için ışık kaynağı ile hedef oda arasında herhangi bir engelin bulunup bulunmadığını kontrol etmemiz gerekir. Benzer şekilde, bir yapay zeka ajanının hedefine doğru ilerlerken rotası üzerinde bir engel olup olmadığını da bu algoritmalar sayesinde tespit edebiliriz.
Çevre modelleme yöntemlerini temel olarak ikiye ayırabiliriz: Izgara (grid) tabanlı ve nesne (vektör/poligon) tabanlı yapılar. Bu yazıda, özellikle performans avantajlarıyla öne çıkan grid tabanlı ışın izleme algoritmalarına odaklanacağız.
Digital Differential Analyzer (DDA) Algoritması
Kare hücrelerden (grid) oluşan büyük bir labirentin içinde olduğumuzu düşünelim. Bu hücrelerin bazıları boş geçitlerden, bazıları ise geçilemez duvarlardan oluşsun. Elimizde de bir lazer var ve bu lazerin duvara ilk çarptığı noktayı hassas bir şekilde bulmak istiyoruz. Bu problemi çözmek için DDA (Digital Differential Analyzer) algoritmasını kullanabiliriz. DDA, bir ışının ızgara tabanlı bir harita üzerinde nasıl ilerlediğini hesaplayan oldukça verimli bir yöntemdir.
Lazer ışınının katettiği her milimetreyi veya pikseli tek tek kontrol ederek hangi hücreye girdiğini bulabilirdik; ancak bu yaklaşım son derece yavaş ve işlemciyi yoran bir yöntem olurdu. Üstelik tam çarpma noktasını bulabilmek için çok sayıda ek hesaplama yapmamız gerekirdi. DDA algoritması ise bu problemi matematiksel olarak çok daha hızlı ve zarif bir şekilde çözer. Işını milim milim ilerletmek yerine, her adımda bir sonraki dikey veya yatay grid çizgisine doğrudan atlamamızı sağlar.
Sembol
Açıklaması
Tipi
rayPosX,rayPosY
Işının başlangıç koordinatı
Girdi
rayDirX,rayDirY
Işının yön vektörü
Girdi
cellWidth/cellHeight
Hücrelerin genişliği ve yüksekliği
Girdi
rayDirLen
Işının yön vektörünün uzunluğu
Ara Değişken
uRayDirX,uRayDirY
Işının yön vektörünün normalleştirilmiş hali
Ara Değişken
sideDistX,sideDistY
İlk hücre sınırına olan uzaklık (sideDist)
Ara Değişken
deltaDistX,deltaDistY
Hücreler arası adım boyutu (deltaDist)
Ara Değişken
stepX,stepY
Eksenlerdeki adım yönü (+1 / -1)
Ara Değişken
intrsX,intrsY
Işın ile duvarın kesişme noktası
Çıktı
DDA Adımları
Adım 1
Işın vektörünün özelliklerini hesapla
Işın yön vektörünün uzunluğunu hesaplayarak başlarız. Bu değer, ışının doğrultusunu ve büyüklüğünü belirlememizi sağlar.
rayDirLen=rayDirX2+rayDirY2
Işın yön vektörünü normalleştirerek birim yön vektörünü elde ederiz.
Burada ise ışının eksenler üzerindeki ilerleme yönünü tespit ederiz. Daha basit bir ifadeyle: Işın X ekseninde pozitif yönde ilerliyorsa stepX değeri +1, negatif yönde ilerliyorsa -1 olur. Aynı tespit stepY ile Y ekseni için de gerçekleştirilir.
Işının kendi doğrultusu üzerinde ilerlerken, tam olarak 1 hücre genişliği (X yönünde) veya 1 hücre yüksekliği (Y yönünde) katetmesi için gitmesi gereken toplam mesafeleri (deltaDistX, deltaDistY) hesaplarız.
Işın genellikle bir hücrenin tam köşesinden değil, herhangi bir iç noktasından başlar. Bu adımda, ışının başlangıç noktasından X ve Y eksenlerindeki en yakın ilk grid çizgisine (hücre sınırına) ulaşması için gitmesi gereken ilk mesafeleri (sideDistX, sideDistY) hesaplarız.
Hangi eksendeki hücre sınırına olan uzaklık (sideDist) daha küçükse, ışın o eksen boyunca bir sonraki hücreye atlatılır. Seçilen eksendeki toplam kat edilen mesafe adım boyutu (deltaDist) kadar artırılır ve harita indeksi (mapX veya mapY) güncellenir.
Işının katettiği toplam mesafe kontrol edilir. Eğer ışın belirlenen maksimum menzili (maxRayLength) aşmışsa, menzil içinde bir engele çarpmadığı kabul edilerek tarama sonlandırılır.
Işının ulaştığı güncel hücrede (mapX, mapY) bir engel veya duvar olup olmadığı kontrol edilir. Eğer bu hücre doluysa, ışının duvara çarptığı tespit edilir.
Eğer 6. adımda bir çarpışma tespit edildiyse, çarpışmanın gerçekleştiği kesin koordinatlar (intrsX, intrsY) hesaplanır ve geri döndürülür. Eğer menzil aşımı veya çarpışma gerçekleşmediyse, ışın bir sonraki adım için Adım 4'e döner ve döngü devam eder.
Lazer ucundan tutup yönünü ve boyunu ayarlayabilirsiniz.
Girdiler
Start:-32.0, 16.0
End:16.0, -16.0
Cell:0.0x0.0
Işın Vektörü
Pos:-32.0, 16.0
Dir:48.00, -32.00
Step:1, -1
DDA Değerleri
Delta:0.00, 0.00
Side:0.0, 0.0
Map:0, 0
DDA Algoritması Örnek Kodları
DDA (Digital Differential Analyzer) algoritmasının Python, Java ve C# dillerinde yazılmış örnek implementasyonlarını aşağıdan inceleyebilirsiniz:
Pratik Uygulama: Görüş Hattı
Izgara (grid) tabanlı bir dünyada ışın izleme, yalnızca teorik bir matematik konusu değil; modern oyun mekaniklerinin en temel yapı taşlarından biridir. DDA algoritması sayesinde, yapay zekanın oyuncuyu görüp görmediğini (görüş hattı) veya dinamik bir ışık kaynağının hangi hücreleri aydınlatacağını son derece yüksek bir performansla hesaplayabiliriz.
Hedef Görünmüyor
Pratik Uygulama: Dinamik Görünürlük ve Görüş Alanı
Bu bölümde, ilk örneğimizdeki dinamik görünürlük ve ışıklandırma sistemini farklı bir harita yapısı üzerinde deneyimleyebilirsiniz. Ajanın 360 derecelik görüş alanını, engellerin bu alanı nasıl gölgelediğini ve ışın izleme mantığının gerçek zamanlı görsel yansımasını burada inceleyebilirsiniz.
Işınlar
16
Pratik Uygulama: LIDAR Sensörü ve Nokta Bulutu Taraması
Gerçek dünyada LIDAR sensörleri, fırlatılan lazer ışınının geri dönme süresini (Time-of-Flight - ToF) ölçerek engellere olan doğrudan mesafeyi tespit eder. Bilgisayar simülasyonlarında ise sanal sensörün bu engelleri ve mesafeyi hesaplayabilmesi için altta DDA (Digital Differential Analyzer) algoritması çalıştırılır. Ajanın merkezinden çıkan tek bir lazer ışını 360° boyunca belirli bir açı adımıyla kesikli olarak döner. DDA ile hesaplanan kesişim noktaları haritada nokta bulutu (point cloud) halinde saklanır. Ajan hareket ettirildiğinde tespit edilen noktalar dünya koordinatlarında sabit kalır; dönen lazer ışını aynı açı adımına ulaştığında noktaları ajanın yeni konumuna göre kademeli olarak günceller.
Işın Adımı
72
Referanslar ve İleri Okuma
Işın izleme (Raycasting) ve DDA (Digital Differential Analyzer) algoritmalarının arkasındaki teoriyi, matematiği ve farklı programlama dillerindeki gelişmiş uygulamalarını daha derinlemesine incelemek için aşağıdaki klasik ve popüler makalelere göz atabilirsiniz: