Takip et

Hareket Kontrollü Akışkan Simülasyonu Geliştirirken GitHub ile Kapışmak

Her şey, gerçek zamanlı fizik simülasyonlarına olan hayranlığımla başladı. Özellikle su, duman gibi akışkanların dinamiklerini dijital ortamda …

Hareket Kontrollü Akışkan Simülasyonu Geliştirirken GitHub ile Kapışmak

Bu makalede, el hareketleriyle kontrol edilebilen etkileşimli bir akışkan simülasyonu geliştirme serüvenimi anlatacağım. Projenin teknik detaylarından, karşılaşılan zorluklara ve bu süreçte GitHub ile yaşadığım beklenmedik “kapışmaya” kadar her şeyi samimi bir dille paylaşacağım. Amacım, benzer projelere girişmek isteyenlere ilham vermek ve olası tuzaklara karşı uyarmaktır.

Proje Fikri ve Motivasyon

Her şey, gerçek zamanlı fizik simülasyonlarına olan hayranlığımla başladı. Özellikle su, duman gibi akışkanların dinamiklerini dijital ortamda canlandırmak, hem görsel açıdan büyüleyici hem de teknik açıdan oldukça zorlayıcı bir meydan okumaydı. Bu projeyi sadece bir akışkan simülasyonu olmaktan çıkarıp, kullanıcıyla etkileşimini artırmak istedim. İşte bu noktada hareket kontrolü fikri devreye girdi.

Neden Akışkan Simülasyonu?

Akışkan simülasyonları, bilgisayar grafiklerinin en karmaşık alanlarından biridir. Navier-Stokes denklemleri gibi fiziksel prensiplere dayanır ve genellikle yüksek işlem gücü gerektirir. Ancak günümüzün modern tarayıcıları ve WebGL gibi teknolojiler sayesinde, bu tür simülasyonları web üzerinde gerçek zamanlı olarak çalıştırmak mümkün hale geldi. Bu alandaki bilgimi derinleştirmek ve pratik bir uygulama geliştirmek istedim.

Hareket Kontrolünün Cazibesi

Kullanıcıların fare veya klavye yerine doğal el hareketleriyle bir simülasyonu kontrol etmesi fikri beni çok heyecanlandırdı. Bu, sadece teknik bir başarı değil, aynı zamanda kullanıcı deneyimini zenginleştiren bir yenilik olacaktı. Sanal dünyayla fiziksel etkileşim kurma potansiyeli, projeye benzersiz bir boyut kattı.

Kişisel Gelişim Hedefleri

Bu proje, sadece eğlenceli bir fikir olmanın ötesinde, benim için bir öğrenme platformuydu. WebGL ile derinlemesine çalışmak, shader programlama (GLSL) becerilerimi geliştirmek, fizik tabanlı simülasyon algoritmalarını uygulamak ve hareket algılama API’ları ile entegrasyon yapmak gibi birçok teknik hedefim vardı. Ayrıca, büyük ve karmaşık bir projeyi baştan sona yönetme deneyimi kazanmak da önemliydi.

Akışkan Simülasyonunun Temelleri

Akışkan simülasyonları, genellikle Navier-Stokes denklemlerinin sayısal çözümlerine dayanır. Bu denklemler, bir akışkanın hızını, basıncını ve yoğunluğunu zamanla nasıl değiştiğini tanımlar. Gerçek zamanlı uygulamalar için bu denklemler basitleştirilir ve genellikle grid tabanlı yöntemlerle çözülür.

Navier-Stokes Denklemleri ve Basitleştirmeler

Navier-Stokes denklemleri, akışkan dinamiğinin temelini oluşturur. Ancak bu denklemlerin doğrudan çözümü son derece karmaşıktır. Gerçek zamanlı simülasyonlarda, genellikle “incompressible” (sıkıştırılamaz) akışkanlar varsayılır ve viskozite gibi bazı terimler basitleştirilir veya tamamen göz ardı edilir. Bu, hesaplama maliyetini düşürerek interaktif deneyimler yaratmamızı sağlar.

Grid Tabanlı Yaklaşımlar

Simülasyon alanı, genellikle bir ızgaraya (grid) bölünür. Her ızgara hücresi, akışkanın hız, yoğunluk ve basınç gibi özelliklerini depolar. En yaygın kullanılan yöntemlerden biri, hız bileşenlerinin farklı noktalarda depolandığı “Staggered Grid” veya “MAC Grid” yaklaşımıdır. Bu, sayısal kararlılığı artırır.

Advection, Diffusion ve Projection Aşamaları

Bir akışkan simülasyonu genellikle şu adımlarla ilerler:

  1. Advection (Taşıma): Akışkanın kendi hızıyla veya dış kuvvetlerle nasıl hareket ettiğini hesaplar.
  2. Diffusion (Yayınım): Akışkanın viskozite nedeniyle nasıl yayıldığını simüle eder.
  3. External Forces (Dış Kuvvetler): Kullanıcının hareketleri veya diğer dış etkenlerin akışkan üzerindeki etkisini uygular.
  4. Projection (Yansıtma): Akışkanın sıkıştırılamazlık koşulunu sağlar, yani akışkanın hacminin değişmediğinden emin olur. Bu adım, basıncı ayarlayarak akışkanın diverjansını sıfıra indirir.

Bu adımlar her karede tekrarlanarak akışkanın dinamiklerini oluşturur. WebGL ile bu adımların her biri ayrı bir shader programı olarak GPU üzerinde çalıştırılır, bu da büyük performans kazancı sağlar.

WebGL ile Gerçek Zamanlı Render

Simülasyonun hesaplamaları genellikle GPU üzerinde dokulara (textures) yazılır. Örneğin, bir doku akışkanın hızını, diğeri yoğunluğunu tutabilir. Bu dokular daha sonra bir fragment shader tarafından okunarak ekrana görsel olarak render edilir. Bu yaklaşım, karmaşık hesaplamaların paralel olarak yürütülmesine olanak tanır ve akıcı bir gerçek zamanlı deneyim sunar.


// Örnek bir advection shader'ından parça
void main() {
    vec2 uv = gl_FragCoord.xy / u_resolution;
    vec2 velocity = texture2D(u_velocityTexture, uv).xy;
    vec2 prevPos = uv - velocity * u_dt; // u_dt zaman adımı
    gl_FragColor = texture2D(u_densityTexture, prevPos);
}

Hareket Algılama Entegrasyonu

Simülasyonun en heyecan verici kısmı, onu el hareketleriyle kontrol edebilmekti. Bu, kullanıcıdan gelen kamera görüntüsünü işleyerek el iskeletini tespit etmeyi ve bu veriyi simülasyona aktarmayı gerektiriyordu.

Kullanılan Sensörler ve API'lar

Başlangıçta farklı yaklaşımları değerlendirdim. Leap Motion gibi özel donanımlar daha hassas veri sunsa da, projenin web tabanlı ve erişilebilir olmasını istediğim için tarayıcı tabanlı çözümlere yöneldim. MediaPipe Hands veya PoseNet gibi kütüphaneler, sıradan bir web kamerası kullanarak el iskeleti tespiti yapabiliyor ve bu verileri JavaScript ortamına aktarabiliyordu. Ben MediaPipe Hands'i tercih ettim çünkü hem performansı iyiydi hem de detaylı el iskeleti verisi sağlıyordu.

Veri İşleme ve Normalizasyon

MediaPipe'tan gelen veriler, kameranın koordinat sisteminde 3D nokta listeleri (el parmak eklemleri) şeklindeydi. Bu noktaların simülasyonun 2D koordinat sistemine dönüştürülmesi ve normalizasyonu gerekiyordu. Örneğin, elin merkez noktasını alıp, ekranın genişliğine ve yüksekliğine oranlayarak 0-1 aralığında bir değere çevirdim. Ayrıca, elin hareket hızını hesaplamak için önceki karedeki konumunu da takip ettim.

Simülasyona Girdi Olarak Aktarma

Normalleştirilmiş el pozisyonu ve hızı, simülasyonun dış kuvvetler aşamasında kullanıldı. Elin hareket ettiği konuma bir "kuvvet" veya "yoğunluk" eklenerek akışkanın o noktada hareket etmesi veya renklenmesi sağlandı. Örneğin, elin hızı ne kadar yüksekse, akışkana uygulanan kuvvet de o kadar büyük oluyordu. Bu, kullanıcının parmağını suya daldırıp karıştırmasına benzer bir etki yarattı.


// Örnek: Hareket verisini simülasyona aktarma
function applyGestureForce(x, y, vx, vy) {
    // x, y: normalize edilmiş el pozisyonu (0-1)
    // vx, vy: normalize edilmiş el hızı
    // Simülasyonun kuvvet dokusuna bu değerleri yaz
    simulator.addForce(x * simulator.width, y * simulator.height, vx * forceScale, vy * forceScale, color);
}

Teknolojik Seçimler ve Geliştirme Süreci

Projenin teknolojik omurgası JavaScript, WebGL ve GLSL üzerine kuruluydu. Bu seçimler, web tabanlı bir uygulama için en uygun ve performanslı çözümleri sunuyordu.

Programlama Dili ve Kütüphaneler

Ana programlama dili JavaScript idi. WebGL API'si doğrudan JavaScript üzerinden kullanıldı. GLSL (OpenGL Shading Language) ise GPU üzerinde çalışan shader programlarını yazmak için kullanıldı. Üçüncü taraf kütüphane olarak, MediaPipe Hands'in yanı sıra, WebGL'i daha kolay yönetmek için Three.js gibi büyük bir framework yerine, daha düşük seviyeli bir WebGL wrapper veya kendi yazdığım yardımcı fonksiyonları kullandım. Bu, performansı optimize etme ve her detayı anlama konusunda bana daha fazla kontrol sağladı.

Geliştirme Ortamı ve Araçlar

Geliştirme ortamı olarak Visual Studio Code kullandım. Canlı yeniden yükleme (live reload) özellikli bir geliştirme sunucusu (örneğin, http-server veya Webpack Dev Server) ile çalışmak, hızlı iterasyonlar yapmamı sağladı. WebGL hata ayıklaması için tarayıcı geliştirici araçlarındaki "WebGL Inspector" gibi eklentiler paha biçilmezdi.

İteratif Gelişim Yaklaşımı

Proje, küçük adımlarla ve iteratif bir yaklaşımla ilerledi. Önce temel akışkan simülasyonunu çalışır hale getirdim, ardından hareket algılamayı entegre ettim ve son olarak ikisini birleştirdim. Her aşamada, performansı ve görsel kaliteyi iyileştirmeye odaklandım. Bu yaklaşım, karmaşık sorunları daha yönetilebilir parçalara bölmeme yardımcı oldu.

GitHub Mücadelesi: Büyük Dosyalar ve LFS

Her şey yolunda giderken, projenin sonlarına doğru GitHub ile beklenmedik bir "kapışma" yaşadım. Simülasyonun doku verileri ve modellemeleri (eğer olsaydı) gibi büyük dosyalar, standart Git'in sınırlarını zorladı.

Simülasyon Verilerinin Boyutu

Akışkan simülasyonu, her ne kadar temel olarak koddan ibaret olsa da, zamanla biriken test verileri, farklı çözünürlüklerdeki önceden oluşturulmuş dokular veya deneme amaçlı videolar gibi dosyalar depoda yer kaplamaya başladı. Özellikle, yüksek çözünürlüklü dokular veya simülasyon çıktıları, Git'in normalde işleyebileceği dosya boyutlarının üzerine çıkabiliyordu. Başlangıçta bu dosyaları görmezden gelsem de, bir noktada bunları versiyonlamak veya en azından depoda tutmak istedim.

Normal Git'in Sınırları

Git, genellikle küçük metin tabanlı dosyalar ve kod için optimize edilmiştir. Büyük ikili dosyaları (resimler, videolar, ses dosyaları vb.) depolamak, deponun boyutunu hızla şişirir ve klonlama, çekme, itme işlemlerini yavaşlatır. Her bir versiyonda bu büyük dosyaların tam kopyasını saklamak, Git'in verimli çalışma prensiplerine aykırıdır. Bu durum, GitHub'ın ücretsiz depolarda uyguladığı boyut limitleriyle birleşince gerçek bir sorun haline geldi.

Git LFS (Large File Storage) Çözümü

Araştırmalarım sonucunda Git LFS (Large File Storage) ile tanıştım. Git LFS, büyük dosyaları Git deponuzdan çıkarıp ayrı bir sunucuda depolayan ve Git deponuzda bu dosyalara sadece birer işaretçi (pointer) bırakan bir Git uzantısıdır. Bu sayede, deponuzun boyutu küçük kalır ve Git'in performansı etkilenmez. Büyük dosyalar sadece gerektiğinde indirilir.

LFS'in Kurulumu ve Kullanımıyla İlgili Sorunlar

Git LFS'i kurmak ve mevcut büyük dosyaları LFS'e taşımak, beklediğimden daha karmaşık oldu. İlk denemelerimde, LFS'i doğru şekilde yapılandıramadığım için dosyalar hala normal Git tarafından izleniyor veya LFS'e taşınmış gibi görünse de depoda yer kaplamaya devam ediyordu. Özellikle geçmiş commit'lerdeki büyük dosyaları temizlemek ve LFS'e taşımak, git filter-branch veya BFG Repo-Cleaner gibi araçlarla uğraşmayı gerektirdi. Bu süreçte yanlışlıkla deponun geçmişini bozmaktan veya önemli verileri kaybetmekten korktum. Birkaç deneme yanılma, bolca Stack Overflow okuması ve GitHub dokümanlarını karıştırmanın ardından, sonunda LFS'i başarıyla entegre ettim ve depomun boyutunu kabul edilebilir seviyelere indirdim. Bu süreç, bana Git'in derinliklerini ve versiyon kontrolünün inceliklerini bir kez daha öğretti.

Karşılaşılan Zorluklar ve Çözümler

Her büyük projede olduğu gibi, bu simülasyonu geliştirirken de çeşitli zorluklarla karşılaştım. Ancak her zorluk, yeni bir şeyler öğrenme fırsatı sundu.

Performans Optimizasyonu

Gerçek zamanlı akışkan simülasyonları doğası gereği yoğun hesaplama gerektirir. Tarayıcıda 60 FPS hedeflemek için ciddi optimizasyonlar yapmam gerekti. Bunlar arasında:

  • Daha düşük çözünürlüklü simülasyon ızgaraları kullanmak.
  • Gereksiz shader işlemlerini kaldırmak.
  • GPU'dan CPU'ya veri transferini minimuma indirmek.
  • Frame Buffer Object (FBO) kullanımını optimize etmek.
  • Tarayıcıda donanım hızlandırmanın doğru çalıştığından emin olmak.

Bu optimizasyonlar sayesinde, çoğu modern tarayıcıda akıcı bir deneyim sunmayı başardım.

Hareket Algılama Doğruluğu

MediaPipe gibi kütüphaneler etkileyici olsa da, özellikle farklı ışık koşullarında veya karmaşık arka planlarda el tespiti bazen hatalı olabiliyordu. Bu durum, simülasyona yanlış girdiler gelmesine neden oluyordu. Çözüm olarak:

  • Gelen veriyi yumuşatmak için basit bir ortalama filtresi (moving average filter) kullandım.
  • Belirli bir güven eşiğinin altındaki tespitleri göz ardı ettim.
  • Kullanıcıya iyi ışıklandırma ve sade bir arka plan sağlama konusunda ipuçları verdim.

Git LFS Konfigürasyon Hataları

Yukarıda bahsedilen Git LFS sorunları, projenin teknik kısmından ziyade operasyonel bir zorluktu. Çözüm, sabırla dokümantasyonu okumak, farklı komutları denemek ve Git'in dahili çalışma prensiplerini daha iyi anlamaktan geçti. Özellikle git lfs migrate import --everything gibi komutları dikkatli kullanmak, deponun geçmişini temizlemek için kritikti.

Hata Ayıklama Stratejileri

WebGL ve GLSL ile hata ayıklama, geleneksel JavaScript hata ayıklamasına göre daha zordur. Tarayıcı geliştirici araçlarındaki WebGL Inspector, shader hatalarını tespit etmede ve doku içeriklerini incelemede çok yardımcı oldu. Ayrıca, simülasyonun ara adımlarındaki dokuları görselleştirmek (örneğin, hız dokusunu renklendirmek), sorunların nerede başladığını anlamamı sağladı.

Sonuç

Hareket kontrollü akışkan simülasyonu projesi, benim için inanılmaz bir öğrenme deneyimi oldu. Akışkan dinamiğinin karmaşıklığından, WebGL'in gücüne, hareket algılamanın inceliklerinden, Git LFS'in derinliklerine kadar birçok alanda bilgi ve becerilerimi geliştirdim. GitHub ile yaşadığım "kapışma" ise, versiyon kontrol sistemlerinin sadece kod depolamaktan ibaret olmadığını, aynı zamanda büyük veri yönetimi gibi operasyonel zorlukları da beraberinde getirebileceğini gösterdi.

Bu proje, teknolojiyle etkileşim kurmanın yeni yollarını keşfetmenin ne kadar ödüllendirici olabileceğini kanıtladı. Umarım bu makale, benzer projelere girişmek isteyen diğer geliştiricilere ilham verir ve karşılaşılabilecek potansiyel zorluklar hakkında bir yol haritası sunar.

SSS (Sık Sorulan Sorular)

1. Akışkan simülasyonu için neden WebGL'i seçtiniz?

WebGL, tarayıcıda doğrudan GPU erişimi sağlayarak, akışkan simülasyonu gibi yoğun grafik ve hesaplama gerektiren uygulamaları gerçek zamanlı olarak çalıştırmak için ideal bir platformdur. JavaScript ile entegrasyonu kolaydır ve ek bir eklenti veya yazılım kurulumu gerektirmez.

2. Hareket algılama için başka hangi kütüphaneleri düşündünüz?

MediaPipe Hands'in yanı sıra, Google'ın PoseNet'ini ve daha eski bir teknoloji olan Leap Motion API'sini düşündüm. PoseNet, vücut pozisyonu tespiti için harika olsa da, el iskeleti detayında MediaPipe kadar gelişmiş değildi. Leap Motion ise özel bir donanım gerektirdiği için projenin genel erişilebilirliği hedefine uymadı.

3. Git LFS kullanırken en çok zorlandığınız nokta neydi?

Mevcut bir Git deposundaki geçmiş commit'lerde yer alan büyük dosyaları LFS'e taşımak en zor kısımdı. Sadece git lfs track komutunu çalıştırmak yeterli olmuyor; geçmişi temizlemek ve deponun boyutunu küçültmek için git filter-branch veya BFG Repo-Cleaner gibi araçlarla deponun tarihçesini yeniden yazmak gerekti. Bu işlemler, doğru yapılmadığında veri kaybına yol açabileceği için oldukça stresliydi.

4. Simülasyonun performansını artırmak için hangi temel optimizasyonları yaptınız?

En temel optimizasyonlar, simülasyon ızgarasının çözünürlüğünü düşürmek, her karede tekrarlanan shader işlemlerini basitleştirmek ve GPU ile CPU arasındaki veri transferini en aza indirmek oldu. Ayrıca, tarayıcıdaki WebGL bağlamının donanım hızlandırmayı kullandığından emin olmak da kritikti.

5. Bu projeyi geliştirirken öğrendiğiniz en değerli ders ne oldu?

En değerli ders, karmaşık bir problemi küçük, yönetilebilir parçalara bölerek adım adım ilerlemenin önemi oldu. Ayrıca, sadece kod yazmakla kalmayıp, kullanılan araçların (Git, GitHub, tarayıcı geliştirici araçları) derinlemesine nasıl çalıştığını anlamanın, beklenmedik sorunlarla başa çıkmada ne kadar kritik olduğunu bir kez daha anladım.

Yorumlar
İçeriği beğendiniz mi? Bir tartışma başlatın veya görüşlerinizi paylaşın.
Yorum Yaz

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

E-posta Bülteni
Yazılım Topluluğuna Katılın
En son güncellemeleri, yaratıcı ipuçlarını ve özel kaynakları doğrudan e-posta kutunuza alın. Tasarım ve inovasyonun geleceğini birlikte keşfedelim.