> Ana Sayfa > Yazılar

Dalga Fonksiyonu Çökmesi: Prosedürel Resim Üretimi

Temel Kavramlar

Dalga fonksiyonu çökmesi algoritması, sınırlı alanlarda olasılıksal düzen üretmek için kullanılan güçlü bir yöntemdir. Özellikle prosedürel içerik üretimi ve otomatik harita tasarımı gibi alanlarda büyük avantajlar sunar. Adını kuantum mekaniğindeki dalga fonksiyonunun çökmesi kavramından alır, ancak algoritma fiziksel bir süreç yerine olasılıklar ve kısıtlar üzerinden çalışır. İzlemesi çok zevkli ve kullanması çok havalıdır.

Kullanım alanları

Oyun geliştirme
En sık kullanımı oyun geliştirme alanındadır. Burada prosedürel üretilen haritalarda kullanılabilir böylece önceden belirlenmiş kurallar çerçevesinde sonsuz olasılıkta harita oluşturabiliriz. Hatta sonsuza giden haritalar yapmak bu algoritma ile mümkündür.
Sanat ve Tasarım
Dalga fonksiyonu çökmesi pixelli görseller oluşturmak için çok uygundur. Örneğin küçük bir desen verdiğinde, algoritma bu deseni genişleterek büyük ölçekli ve benzer tarzda ama rastgele varyasyonlara sahip yeni görüntüler üretebilir. Örneğin, bir oyun için otomatik olarak rastgele fakat uyumlu duvar dokuları, yer karoları veya harita desenleri oluşturabilir.
Skyline
Ya da yandaki gibi örnek resim verip arkaplan görüntüsü oluşturabiliriz. Çıktının solu ile sağını birbiri ile bağlantılı yaparak akıcı sonsuz bir döngü oluşturabiliriz.
  • Yapay Zeka ve Modelleme
  • Bu yazıda bu algoritmanın daha çok görsel yönüne odaklanacağız. Ama bu algoritma aynı zamanda yapay zeka ve modelleme alanında da kullanılabilir. Bu algoritma, makine öğrenmesi gibi büyük veri kümeleri gerekmeden, küçük veri kümesinin kısıtlarından yeni içerik oluşturabilir.

    Çalışma Mantığı Özeti

    Dalga fonksiyonu çökmesine en iyi örnek sudokudur. Bir karenin içini doldurduğunuzda diğer karelerin üzerindeki kısıtlar artar. Örneğin bir kareye 2 yazdığınızda artık o büyük karede, satırda ve sütunda 2 yazamazsınız. 2 yazmanızdan direkt etkilenen kareler de kendi etki alanlarına etki ederek tüm haritaya yayılır.

    Algoritmanın Çalışma Prensibi

    Temel Kavramlar

    • Desen: Desen, hücreye çökecek olan veridir.
    • Hücre: Çıktımızın bir karesidir. Çıktımız bir kareler kümesidir. Kareler bu desenlerle doldurulur.

    Adım Adım Çalışma

    Adım 1: Giriş Verisi

    • Algoritma başlamadan önce kullanılacak desenler belirlenir.
    • Bu desenler, hangi diğer desenlerle yan yana gelebileceği bilgisiyle birlikte tanımlanır veya biz bunu desenin görselinden otomatik oluştururuz.
    • Desenlerimizin ağırlıkları mevcuttur. Böylece daha çok seçilmesini istediğimiz desenin ağırlığını arttırırız.
    • Örneğin ağırlığı 5 olan desenin, ağırlığı 1 olan desene kıyasla seçilme ihtimalı 5 kat fazladır.

    Adım 2: Desenlerin birbiri ile ilişkileri belirlenmesi

    • Her desenin hangi yönlerde (üst, alt, sağ, sol) hangi diğer desenlerle uyumlu olduğu kaydedilir.
    • Örneğin, sol tarafında boru bağlantısı olan bir desen, sol tarafı için yalnızca sağ tarafında boru bağlantısı bulunan bir desenle eşleşebilir.
  • Buraya kadar anlattıklamınızı koda geçirelim. Bunun için Pattern sınıfı oluşturdurm.
  •             
            

    Adım 3: Hücrenin tanımlanması

    • Grid, her biri başlangıçta tüm desenlere sahip olabilen hücrelerden oluşur.
    • Örneğin 10x10 boyutunda grid yapımız olsun diyelim. Bu yapı 100 hücreden oluşur
    • Hücreler, algoritma ilerledikçe desenler elenir ve sadece uygun desenler kalır. Bu sayede büyük resim şekillenmeye başlar.

    Mevcut desen listesi:

    • Bu hücrede halen seçilebilecek desenleri içerir.
    • Algoritma çalışırken kurallar nedeni ile daralır ve en sonunda ek bir elemana indirgenir.
    • Örneğin başlangıçta her hücrede 4 farklı desen olabilir: 🟥 🔵 🟩 🟨. Eğer bir seçim yapıldığında kırmızı yasaklanırsa, bu liste artık sadece 🔵 🟩 🟨 içerir.

    Uyumlu desenler listesi:

    • Bu, komşu hücrelerle uyumlu olan desenlerin bir haritasıdır.
    • Hücrenin her yönü için hangi desenlerin uygun olduğunu belirtir. Her yön için ayrı bir koleksiyon tutulur.
    • Örneğin eğer bir hücrede sadece 🔵 ve 🟩 kalmışsa, yanındaki hücrede 🔵 ve 🟩 ile uyumlu olan desenler kalmalıdır.
      Bir desene uyumlu birden fazla uyumlu desen olabilir o yüzden bu koleksiyonu sayılarla tutarız. Örneğin sol hücresi için 🟩 desenini destekleyen kaç tane desen vardır. Bu sayının sıfıra düşerse komşusundaki 🟩 desenini yasaklarız.

  • Hücre sınıfının özelliklerini inceleyelim:
  •             
            
    • T Generik tipi hücrenin alacağı desen tipidir.
    • X ve Y, hücreminizin griddeki kordinatını temsil eder.
    • ObservedPattern, hücre çoktükten sonra geriye kalan tek desendir. Hücrenin çöküp çökmediğini de bu değişkenden anlayabiliriz.
    • AvailablePatternList, mevcut desen listesidir.
    • CompatiblePatternList, uyumlu desen listesidir.

    Adım 4: Dalga fonksiyonu çökmesinin ana hatları

    • İstenen yükseklik ve genişlik boyutunda liste oluşturulur. Örneğin 5x5 boyutundaki çıktımız için 25 adet hücrenin oluşturmamız gerekir.
    • Bir hücrenin yanlarındaki hücreleri getirecek fonksiyon yazarız. Bu fonksiyonda önemli bir ayrıntı hücrelerin bulunduğu grid'in periyodik olup olmamasıdır.
    • Örneğin 5x5 boyutunda bir hücre listesini ele alalım. (2,4) noktasında bulunan hücrenin üstündeki hücre tekrar (2,0) oluyorsa y ekseni boyunca periyodiktir.

    Adım5: Dalga fonksiyonu çökme algoritması

    • İlk olarak hücrelerimizi oluştururuz ve tüm hücrelelerin içerisine tüm desenleri ekleriz.
    • Uygun desen listesi doldurulur. Dolma yöntemi mevcut desen listesindeki desenlere dayanarak o desenlerin yanlarında hangi desenlerin kaç desen tarafından desteklendiğini kaydederiz: Örneğin hücrenin soluna yönüne 🔵 deseninin alabilecek kaç desen olduğunu buluruz. Bunu her desen için yaparız. Bunu yapmanın pratik yolu seçtiğimiz desenin tersi yönünde bağlantı yapabileceği desen sayısıdır.
    • Çökecek hücreyi seçeriz. Seçim için farklı algoritmalar kullanılabilir. Örneğin, Shannon Entropisi yöntemi kullanılarak en düşük bilgi içeriğine sahip hücre belirlenebilir ve bu sayede çıkmaz durumları daha da azaltılabilir. Ancak, ben algoritmanın karmaşıklığını artırmamak adına gözlenmemiş mevcut desen listesi eleman sayısı en küçük hücreyi seçerek ilerleyeceğim.
                
            
    • Gözlemlenecek hücreyi seçtik artık hücreyi gözleyebiliriz. Burada hücrenin tüm desenlerinden ağırlıları oranla rastgele seçim yapılır. Seçilen desen hücrenin gözlemlenen desen değerine yazılırken, mevcut desen listesindeki diğer desenler yasaklanır.
                
            

    Yasaklama(Ban) Fonksiyonu

    Yasaklama hücrenin parametredeki deseni almasını ihtimalini ortadan kaldırmasıdır. Bunu mevcut desen listesininden o deseni silerek ve bu hücreye bakan uygun desen listelerindeki yasaklanan desenin değeri sıfıra çekerek yaparız. Fonksiyonun sonunda da deseni yasaklanan desen yığınına ekleriz. Bu yığını Yayılım(Propagate) aşamasında kullanacağız.
                
            

    Yayılım(Propagate) fonksiyonu

    • Yayılma fonksiyonumuzdaki işlemler yasaklanan desen yığını bitene kadar devam eder.
    • Yığındaki elemanı alırız ve elemanı yığından kaldırırız.
    • Her bir yön için tekrar çalışır.
    • Sonrasında yasaklanan desenin mevcut yön için uygun desen listesini alırız.
    • Hücrenin uyumlu desen listesinden bu desene karşılık gelen sayılar birer kez azaltılır.
    • Bu azaltılma sonucu sayı 0 olursa, 0'a düşmüş değeri o yöndeki hücreden de yasaklarız.
                
            
    • Tüm bu adımlardan sonra gözlenmemiş hücre varsa tekrar sonraki gözlenecek hücreyi seçeriz. Bu tüm hücreler çökene kadar devam eder.
    • Dalga fonksiyonu çökmesinin temeli bu adımlardır. Yukarıdaki fonksiyonları tamamını WaveFunctionCollapse sınıfında birleştiririz.
                
            

    Basit Döşeme Metodu

    Simple Tiled
    Basit Döşeme Metodu, kullanıcının belirlediği desenleri kullanarak bir alanı kaplamayı amaçlayan bir dalga fonksiyonu çökmesi algoritmasıdır. Bu yöntem, önceden tanımlanmış bir desen kümesi ile çalışır ve tüm desenlerin belirli kurallar çerçevesinde yerleştirilmesini sağlar.

    Basit döşeme methodu deseni

    Yukarıdaki desene iki ilave bilgi daha eklememiz gerekir.
    • Birincisi resmin kendisidir.
    • İkincisi resmin dönüştürme(Translate) operatörlerinin toplamıdır. Dönüşüm matrisleri ile nasıl poligonları değiştirebileceğimizi daha önceki yazımda anlatmıştım. Daha detaylı bilgi için o yazımı okuyabilirsiniz
                
            

    Basit döşeme methodu manuel desen bağlantı oluşturma yöntemi

    Desenlerin ilişkilerini manuel sayılar girerek hangi desenlerin birbiri ile bağlantı kuracağını belirleyebiliriz. İki desenin birbirine bakan yönlerindeki sayılar karşılaştırılır. Bu iki sayıya 've' işlemi uygulandıktan sonra, kalan değer 0'dan büyükse fonksiyon 'true' döner. Değilse yanlış olarak döner. Manuel karşılaştırma bize çok büyük bir özgürlük verir. Hangi desenin hangi desenle komşu olabileceği bilgisini tamamen yönetmiş oluruz. Ancak buna karşın her bir desen için ve her bir yön için sayıları atamak yorucu olabilir.
                
            
    Bitwise operatörleri kullanmamızın sebebi, bağlantı kurallarını hafızada verimli bir şekilde saklamak ve hızlı karşılaştırmalar yapabilmektir. Alternatif olarak string veya liste karşılaştırmaları da yapılabilir, ancak bitwise işlemler bu süreci daha hızlı ve esnek hale getirir.
    Burada bitwise operatör kullanmamızın sebebi örnekle anlatmak daha iyi olacaktır. 🟥, 🔵, 🟩 şeklinde 3 desenimiz bulunsun. 🟥 her yönüne yine 🟥 gelebilir ve Aynı şekilde 🔵 deseninin de her yönüne 🔵 gelebilir varsayalım. 🟩 desenide etrafına da tüm desenler gelebilirse bunu betimlemek için en iyi yol bitwise operatörlerdir. 🟥 deseninin bağlantı değerini 01, 🔵 deseninin bağlantı değerini 10 yaparsak kendi içlerinde bağlantı kurabilir ve birbirleri ile bağlantı kuramazlar. 🟩 deseninin bağlantı değerini 11 yaparak 🟥, 🔵, 🟩 hepsi ile bağlantı kurabilmektedir.
                
            
  • Manuel bağlantı için, basit döşemeye özel desen sınıfını türeterek yeni bir sınıf oluşturduk. 4 farklı yön için değer ekledik.
  • Basit döşeme methodu otomatik desen bağlantı oluşturma yöntemi

    Otomatik desenlerin sınırdaki pixellerine dayanarak iki desenin komşu olup olamayacağını verir. Manuel karşılaştırmada desenlere yön değeri atamamız gerekirken otomatik karşılaştırmada da desenlerimizin resmini algoritmaya göre tasarlamamız gerekir. Bunun için yön değerlerini sayılar yerine pixel listeleri ile değiştirip yeni desen sınıfımızı oluşturabiliriz.
                
            
    Karşılaştırma olarak iki desenin birbirine bakan iki yönündeki pixeller birebir eş mi diye kontrol edebiliriz. Bu bir yöntemdir ama bu da çapraz bağlantı kurmamızı engelleyecektir.
    Örnek olarak:
    ÇaprazBağlantı
    Bu iki desenin birbirine bağlanmasını bekleriz ama birbirine bakan yönlerin kenarlarında pixeller birbirine eş değil. Sadece doğrudan sınırdaki piksele bakmak bazen fazla katı olabilir. Bunun yerine, keskinlik (precision) parametresi ile komşu desenler arasındaki geçişi daha esnek hale getirebiliriz. Algoritma, tam olarak aynı piksel eşleşmesi beklemek yerine, üstündeki veya altındaki piksellerden en az biri uyuyorsa, deseni geçerli kabul ediyor ve sıradaki karşılaştırmaya geçiyor.
    Keskinlik:
    Yukarıdaki interaktif görselde keskinlik değerini daha iyi anlayabiliriz. Yeşil bağlantı pixellerin aynı olduğunu kırmızı farklı olduğunu söylemektedir. Keskinlik arttıkça bir pixelin diğer desende eşleşleşebileceği pixel sayısı artar. Ve her iki desenden de yalnızca bir yeşil çizgi görmemiz o pixelin bağlantıya engel olmadığını gösterir. Bu gibi hiç bir pixel engel olmuyorsa iki desen arasında bağlantı bulunmaktadır.
                
            

    Desenlerimizi oluşturmak için jsondan veri okuma:

    Kök nesnemizde dosyalarımızın konumu, kesinkinlik ve desen kümemiz bulunmaktadır. Desen kümemizde ise resim dosyasının yolu, dönüşüm operasyonları listesi ve ağırlık bulunmaktadır. Eğer manuel bağlantı yöntemini kullanacaksak bunlara ilave olarak yön değerlerini de eklememiz gerekir.
    Dönüşüm operatörleri daha önce de belirttiğim gibi yansıtma ve döndürme işlemi yaptığımız yerdir. Buranın liste olmasının sebebi bir desen kümesinden kaç tane dönüşüm operatörü tanımlandıysa o kadar desen üretilebilir.
    Örnek olarak: "transformOperations": [null, "rotatePi(0.5);", "rotatePi(1);", "rotatePi(0.5);reflectX;",] demiş olalım. Buradan 4 farklı desen çıkar. İlki null olan desenin orjinal halidir, diğerleri de döndürülmüş/simetrik halleridir. Manuel bağlantılı ise nesneyi dönüştürdüğümüzde tabi ki bağlantı değerleride kullandığımız operatöre göre değişmeli.
                
            
    Çıktı X ekseninde periyodik mi?
    Çıktı Y ekseninde periyodik mi?
                
            
    Dalga fonksiyonu çökme üzerine bu iki fonksiyonu tanımlarsak basit döşeme methodunu uygulayabiliriz. WaveFunctionCollapse sınıfından türetilmiş SimpleTiledCollapse bu şekilde olur.

    Örtüşmeli Metod

    Overlapping
    Örtüşmeli Metot, bir şablon resimden otomatik olarak desenleri çıkaran ve bu desenlerin birbirleriyle nasıl hizalanacağını belirleyen bir yöntemdir.
    • Kullanıcının manuel olarak desen tanımlamasına gerek kalmaz.
    • Algoritma, desenleri ve bağlantılarını otomatik olarak oluşturur.
    • Basit döşeme metodunda kullanıcı, girdi olarak tüm desenleri bazende bağlantı kurallarını manuel olarak tanımlamak zorundadır. Örtüşmeli Metot’ta ise yalnızca şablon resim yeterlidir.

    Örtüşmeli method parametreleri

    • Şablon resmi: Burada desen kümesi yerine bir tane örnek şablon içeriğimizi üretmemiz için yeterli olacaktır.
    • Desen büyüklüğü: Şablonumuzdan desen kaydederken desenimizin boyutunu belirler. Örneğin 3 ise desenimiz 3x3 = 9 pixeldir. Bu sayı arttıkta kısıt artar.
    • Şablonumuz X/Y ekseninde periyodik mi: Şablon resmimizin x ekseninde periyodik olup olmadığı bilgisidir. Eğer aktifse, desenin sağ/sol veya üst/alt uçları birleşerek devamlılık sağlar.
    • Şablonumuz X/Y ekseninde simetrik mi: Şablon resminin yatay eksende simetriğinin kullanılıp kullanılmayacağı bilgisidir. Eğer açık olursa, algoritma her desene yatay veya dikey simetrisini de ekler.
    • Şablonumuz 90 derece dönebilir mi: Şablon resminin dönmüş halinin kullanılıp kullanılmayacağı bilgisidir. Eğer bu 'true' ise desenleri tararken, oluşturduğumuz her bir desen için bir de döndürülmüş halini de oluşturmamız gerekir.
    • Yukarıdaki 2 madde bir birleri ile birleşebilir. Bu durumda her bir kombinasyonu tek tek oluşturmamız gerekir.

    Örtüşmeli döşemede desen oluşturma

    Öncelikle her bir pixel dahil olması için yatayda ve dikeyde döngü oluşurulur. Eğer şablonumuz periyodik ise şablonumuzun sonu ile başı birleşir. Değil ise birleşmemesi için desen boyutunun bir eksiği çıkartılır.
    Bu iki döngü içerisine desen boyutundaki karenin pixelleri yeni oluşturduğumuz pixel array'ine kaydedilir. Bu bizim desenimizdir. Elde ettiğimiz desen daha önce kaydedildi ise kayıtlı desenin ağırlığı 1 arttırılır. Daha önce kaydedilmemiş ise ağırlığı 1 olarak desenimiz kaydedilir. Eğer şablonumuzun simetrik durumları da kapsıyorsa yukarıda oluşturduğumuz desenin simetrik durumları için de aynı işlemler yapılır.
                
            
    Desen boyutu
    Şablon X ekseninde periyodik mi?
    Şablon Y ekseninde periyodik mi?
    Şablon X ekseninde simetrik mi?
    Şablon Y ekseninde simetrik mi?
    Şablon 90 derece dönebilir mi?
    Tuğlalar
    Tuğlalar
    Çiçek
    Çiçek
    Labirent
    Labirent
    Platfrom
    Platfrom
    Lağım
    Lağım
    Plaza
    Plaza
    Köy
    Köy
    Yukarıdaki görselde periyodikliğin, simetrinin ve dönme özelliğinin desen oluşturmada nasıl etki ettiğini görebilirsiniz. Yukarıdaki her bir küçük kare birer desen, içlerinde yazan sayıda bu desenlerin ağırlıkları. Yukarıdaki özellikleri aktif edip, arttırarak şablondan elde edilebilecek maksimum desen sayısını arttırabiliriz. Ama tabiki şablonumuzun buna uygun olması gerekmekte yoksa çıktımız istediğimiz gibi olmaz. Çıktının nasıl değiştiğini aşağıdaki interaktif örnekte göreceğiz.

    Örtüşmeli döşemede desen bağlantı karşılaştırması

    Buradaki karşılaştırmamız desenlerin pixelleri üzerinden olacak. Örnek olarak yukarı yönü için bir karşılaştırma yapılıyor olsun. Burada beklenen birinci desenin alt satırı ile ikinci desenin üst satırı çıkartılarak karşılaştırılır. Tüm pixeller aynı ise bağlantı fonksiyonu true döner. Aşağıda sağ bağlantı için örnek gösterilmiştir.
                
            
    Indisi 0 olan desen ile indisi 0 olan desen, sağ yönünde
    uyumlu değil
    Tuğlalar
    Tuğlalar
    Çiçek
    Çiçek
    Labirent
    Labirent
    Platfrom
    Platfrom
    Lağım
    Lağım
    Plaza
    Plaza
    Köy
    Köy
    Bu interaktif örnekte iki desenin yan yana gelebileceği karşılaştırılmaktadır. Karşılaştırılan iki dörtgen birbirine tamemen eş ise desen birbirine uyumlu olur.

    Örtüşmeli döşeme methodu görselleştirme

    Yukarıdaki adımlarla desenlerimizi tanımladığımıza göre artık fonksiyonu başarı ile çalıştırabiliriz. Hücrelerimiz çöktükten sonra çizerken dikkat etmemiz gereken tüm çökmüş hücrelerin desenleri alınırken sadece 1 pixel alınır. Örneğin desenimiz eğer 3 genişliğinde ise içerisinde 9 pixel vardır. Bunun sadece 1 tanesini seçip hücremizi onunla dolduracağız. Ve seçtiğimiz pixel konumu tüm desenlerde aynı olmalıdır. Buradan yola çıkarak en basit şekilde desenin (0,0) pixelini tercih edebiliriz.
    Desen boyutu
    Şablon X ekseninde periyodik mi?
    Şablon Y ekseninde periyodik mi?
    Çıktı X ekseninde periyodik mi?
    Çıktı Y ekseninde periyodik mi?
    Şablon X ekseninde simetrik mi?
    Şablon Y ekseninde simetrik mi?
    Şablon 90 derece dönebilir mi?
    Tuğlalar
    Tuğlalar
    Çiçek
    Çiçek
    Labirent
    Labirent
    Platfrom
    Platfrom
    Lağım
    Lağım
    Plaza
    Plaza
    Köy
    Köy
    Yukarıdaki interaktif örnekte örtüşmeli methodun çıktısını görebilirsiniz. Methodun parametreleri ile oynayıp çıktının nasıl değiştiğini kendi gözlerinizle görebilirsiniz.
                
            

    Çıkmaz durum

    Contradiction
    Dalga fonksiyonu çökme algoritması her zaman kusursuz çalışmamaktadır. Bir hücrenin komşuları öyle desenler almıştır ki o hücrenin alabileceği desen kalmamıştır. Bu duruma çıkmaz durum(contradiction) denir Çıkmaz durumlar desen elemeleri sonucunda hücrelerin içinde hiç uygun desen kalmaması durumudur. Bunun olmasını engellemek için desen kısıtlarını gevşetmek, yeni desen eklemek gereklidir yada kısıtları azaltmak gerekir. Örneğin çıktının periyodik olması yukarısı ve aşağısı arasında bir bağlantı oluşturduğu için çıkmaz durum ihtimalini arttırır.

    Örtüşmeli döşeme'de çıkmaz durum ihtimalini azaltma

    Örneğin yukarıdaki resimde eğer desen boyutunu 5 yaparsanız ve simetrikleri kapatırsanız çalışırken muhtemelen çıkmaz durum gerçekleşecektir. Desen boyutunu ne kadar büyütürseniz orijinal görsele o kadar benzeyecektir ama bu da desenlerin birbiri ile uyumlu olma ihtimalini düşürecektir. Bunun olmasını önlemek için şablon resmin boyutunu büyütebiliriz, daha az renk içeren şablonlar tercih ederiz yada şablonun periyodikliği ve döndürülebilir yapabiliriz. Daha az renk içeren bir şablon kullanarak desenlerin birbiri ile uyumlu olma ihtimalini arttırabiliriz. Eğer şablonun resimini büyütürsek daha fazla desen elde ederiz bu da çıkmaz durumun olma ihtimalini düşürür. Şablonu büyütmek dışındaki çözümler çıktımızı istenenden uzaklaştırabilir. Örneğin köy şablonunu y ekseninde simetrik yaparsak ters evler üretmeye başlayacaktır. Ya da şablonun periyodikliğini ve döndürülebilirliğini arttırarak mevcut şablondan daha fazla desen elde edebiliriz.

    Basit döşeme'de çıkmaz durum ihtimalini azaltma

    Basit döşeme methodunda da mevcut desen sayısını arttırabiliriz, desenlerin birbiri ile daha uyumlu yapabiliz. Basit döşemeye özel olarak, her desenle uyumlu ve ağırlığı çok düşük desen eklersek çıkmaz durumu kesinlikle engelleyecektir. Ama bu çıktıya alakasız hücreler ekleyecektir.

    Çıkmaz durum çözümleri

    Eğer çıkmaz durum gerçekleşti ise en kolay çözüm şimdiye kadar üretilmiş çıktıyı silip algoritmayı tekrar başlatmaktır. Eğer üretimi canlı olarak kullanıcıya veriyorsak yukarıdaki çözüm yerine, çıkmaz durum gerçekleştiğide yapılan işlemleri sırayla geri alıp başka bir deseni yasaklamaktır. Yani geri izleme tekniği kullanmaktır. Bu çözüm hali hazırda orta düzeyde karmaşık olan kodu daha da karmaşıklaştıracağı için bu yazımda anlatmamaya karar verdim. Sayfamda gördüğünüz dalga fonksiyonu çökme çıktılarında ilk anlattığım çözümü uyguladım.

    İlave Başlangıç koşulu: Zemin ve tavan ekleme

    Ground and Ceil
    Bazı durumlarda, algoritma zemin ve tavanın doğru yerlere oturmasını sağlayamaz. Bunun nedeni, hangi desenlerin zemin veya tavan olduğunu bilmemesidir. Eğer bu bilgiyi önceden tanımlayabilseydik, algoritmayı daha kontrollü çalıştırabilirdik. İşte bunu nasıl yapabileceğimizi bu bölümde anlatacağım.

    Basit döşemede zemin

    Yukarıdaki basit döşeme methodunda bunu çok iyi bir şekilde anlayabiliriz.
    • Öncelikle, hangi desenin zemin olduğu bilgisi kullanıcıdan gelmeli.
    Zemin desenleri:
    YerAğaç
    • Karıştırılmaması için belirtiyorum zemin desenleri zemin ve altında altında kalan tüm desenler değildir. Sadece zemin hizasında kalan desenlerdir. Zeminin altında kalan desenler zaten bilgi yayılım aşamasında kendilğinden ortaya çıkacaktır.
    • Burada çıktımızın 2. satırı zemin olarak işeretledik ve bu satırdaki döşemelerden zemin olmayan tüm desenleri yasakladık.
    • Aynı şekilde de zemin döşemesi olmayan satırlardan da tüm zemin desenlerini yasakladık.
    • Ve son olarak bu yasaklar sonucu oluşan bilgiyi de hücrelerimiz boyunca yaydık.
    Böyleye başlangıç olarak elimizde istediğimiz satırda zemin olan hücre seti elde ettik. Bundan sonrası bildiğimiz basit döşeme yöntemi.
                
            

    Örtüşmeli döşemede zemin ve tavan

    Tavan satırının, zemin satırından çalışma prensibinde hiç bir farkı bulunmamaktadır. Biri diğerinin üstünde olduğu için bu isimlendirmeyi tercih ettim. Örtüşmeli döşemede zemin/tavan bilgisini kullanıcıdan sayı olarak alırız. Buradan aldığımız sayının karşılındaki olan şablondaki satırı zemin olarak işaretleriz.
    Çiçek zemin ve tavan
    Örneğin, daha önce kullandığımız çiçek şablonunu ele alalım. Yandaki görselde, tavan olarak belirlenen satır mavi ile taranmıştır. Algoritma, bu satırdaki tüm desenleri "tavan desenleri" olarak kabul eder. Aynı şekilde, siyah alan içindeki desenler "zemin desenleri" olarak tanımlanır. Bu sayede, algoritma zemin ve tavan desenlerini doğru şekilde sınıflandırabilir.
    Bu iki zemin tipinden yola çıkarak tüm desenleri kümelere ayırabiliriz. Böylece 4 farklı kümemiz oluşur.
    Zemin desenleri:
    Zemin olmayan desenler:
    Tavan desenleri:
    Tavan olmayan desenler:
    Hangi desenlerin zemin hangi desenlerin tavan olduğu bilindikten sonra daha sonra çıktımızı oluşturabiliriz. Desenin Y ekseni üzerinde yapılan her değişiklik, zemin ve tavan oluşturma işlemine zarar verir. Örneğin Y eksenine göre simetriğini alırsak yada döndürürsek artık düzgün bir zemin çıktısı almayız.
    Platfrom
    Platfrom
    Plaza
    Plaza
    Çiçek
    Çiçek
    Desen boyutu
    Şablon X ekseninde periyodik mi?
    Şablon Y ekseninde periyodik mi?
    Çıktı X ekseninde periyodik mi?
    Çıktı Y ekseninde periyodik mi?
    Şablon X ekseninde simetrik mi?
    Şablon Y ekseninde simetrik mi?
    Şablon 90 derece dönebilir mi?
    Şablonun Y ekseninde zemin indeksi(Yukarıdan aşağıya)
    Çıktının Y ekseninde zemin indeksi(Yukarıdan aşağıya)
    Şablonun Y ekseninde tavan indeksi(Yukarıdan aşağıya)
    Çıktının Y ekseninde tavan indeksi(Yukarıdan aşağıya)
    Tüm yukarıda anlattıklarımı OverlappingCollapse üzerinde ufak değişikliklerle oluşturabiliriz.
                
            

    Sonuç

    Dalga fonksiyonu Çökmesi (WFC) algoritması, prosedürel içerik üretimi ve otomatik harita oluşturma gibi alanlarda güçlü bir araçtır. Basit Döşeme ve Örtüşmeli Döşeme gibi farklı yöntemler kullanarak, manüel veya otomatik olarak tanımlanan desenler üzerinden yapı oluşturulmasını sağlar.
    Algoritmanın en büyük avantajı, küçük bir veri setinden geniş ölçekli, tutarlı ve rastgele varyasyonlara sahip içerikler üretebilmesidir. Özellikle oyun geliştirme, harita tasarımı ve görsel sanatlar gibi alanlarda daha önce manuel yapılması gereken işlemleri otomatize ederek büyük ölçüde zaman kazandırır. Ayrıca, desen bağlantılarının manuel olarak belirlenmesi sayesinde kullanıcıya tam kontrol sunarken, otomatik desen tanımlama ile esneklik ve ölçeklenebilirlik sağlar.
    Ancak, WFC'nin bazı sınırlamaları da vardır. Büyük ölçekli haritalarda hesaplama maliyeti artabilir ve yanlış kurallar veya yetersiz desen kümesi nedeniyle çıkmaz durumlar (contradictions) oluşabilir. Özellikle desen kümelerinin kötü tasarlanması, algoritmanın başarısını doğrudan etkileyebilir. Bu tür durumları önlemek için desen setlerinin dikkatlice seçilmesi ve kuralların doğru belirlenmesi gereklidir.

    Kaynakça

    https://github.com/mxgmn/WaveFunctionCollapse
    Çoğı kişinin bu algoritmayı geliştirirken referans aldığı kaynak. Ben de bu projeye bakarak dalga fonksiyonu çökme algoritmasını anladım. Ama projenin yazım şekli çok düşük seviye. Sadece projeye bakarak anlamanız zaman alabilir. Desen setlerini ve şablon resimlerin büyük bir kısmını da bu projeden aldım.
    https://kenney.nl/assets/pixel-platformer
    Basit döşeme methodunda zemin ve tavanı olan deset seti için bu asset'i kullandım. Asset içeriğini otomatik eşleştirme sağlaması için değiştirdim.