Simulasi erosi permukaan berbasis partikel


Catatan: kode sumber lengkap proyek, serta penjelasan tentang penggunaan dan bacaannya, dapat ditemukan di Github [di sini ].

Saya mengambil jeda dari tesis master saya untuk mengerjakan apa yang telah saya tunda sejak lama: pembangkitan medan yang lebih baik untuk proyek Territory saya . Cara sederhana untuk mengimplementasikannya adalah erosi hidraulik, itulah sebabnya saya membuatnya!

Untuk puzzle perangkat lunak satu hari, itu bekerja cukup baik, dan tidak serumit yang saya harapkan. Hasil dengan cepat dihasilkan, memiliki makna fisik, dan terlihat luar biasa.

Pada artikel ini, saya akan berbicara tentang implementasi C ++ sederhana saya dari sistem erosi hidrolik mesh-based partikel. Saya akan menjelaskan semua justifikasi fisik yang mendasari implementasi, dan berbicara tentang matematika. Kode ini sangat sederhana (hanya sekitar 20 baris untuk matematika erosi) dan cepat untuk diterapkan, jadi saya merekomendasikannya kepada siapa saja yang ingin meningkatkan realisme medan mereka.

Hasilnya disajikan menggunakan versi stripped down Homebrew OpenGl Engine saya , yang saya modifikasi untuk membuat array 2D poin sebagai peta ketinggian. Versi strip-down engine jauh lebih mudah dipahami jika Anda tertarik mempelajari OpenGL di C ++.

Penerapan


Terinspirasi oleh banyak sumber erosi hidrolik, saya memutuskan bahwa akan lebih logis untuk menggunakan partikel.

Erosi berbasis partikel sangat sederhana:

  • Kami membuat partikel pada titik acak di permukaan.
  • Ini bergerak / slide di sepanjang permukaan menggunakan mekanika klasik standar (kita akan membicarakannya di bawah)
  • Kami melakukan transfer materi / sedimen antara permukaan dan partikel (ini juga dijelaskan di bawah)
  • Kami menguapkan bagian dari partikel
  • Jika partikel berada di luar peta atau terlalu kecil, maka hancurkan
  • Ulangi proses ini dengan jumlah partikel yang diinginkan.

Catatan: parameter sistem dijelaskan di bagian terkait. Yang paling penting adalah faktor langkah waktu dt, yang mengukur semua parameter secara proporsional. Ini memungkinkan kita untuk meningkatkan frekuensi simulasi (dengan biaya peningkatan noise) tanpa mengubah skala relatif dari parameter. Ini bisa dilihat pada kode di bawah ini.

Partikel


Untuk melakukan ini, saya membuat struktur partikel sederhana yang berisi semua properti yang saya butuhkan:

struct Particle{
  //Construct particle at position _pos
  Particle(glm::vec2 _pos){ pos = _pos; }

  glm::vec2 pos;
  glm::vec2 speed = glm::vec2(0.0); //Initialize to 0

  float volume = 1.0;   //Total particle volume
  float sediment = 0.0; //Fraction of volume that is sediment!
};

Catatan: jika Anda tidak terbiasa dengan pustaka GLM: Saya menggunakannya untuk melakukan operasi vektor.

Sebuah partikel memiliki posisi dan kecepatan yang menentukan bagaimana ia bergerak. Selain itu, ia memiliki volume dan sebagian kecil yang menentukan berapa banyak volume batuan sedimen.

Gerakan: mekanika klasik


Pergerakan partikel pada permukaan disimulasikan menggunakan mekanika klasik . Singkatnya, posisi x partikel diubah oleh kecepatan v , diubah oleh percepatan a .



Catatan: huruf tebal menunjukkan bahwa nilainya adalah vektor.

Kita juga tahu bahwa gaya sama dengan percepatan masa massa:


Partikel mengalami akselerasi ke bawah yang disebabkan oleh gravitasi, tetapi berada di permukaan, yang membuat akselerasi ke bawah tidak mungkin. Oleh karena itu, alih-alih ini, partikel dikenai gaya F yang diarahkan sepanjang permukaan dan sebanding dengan normal ke permukaan.

Oleh karena itu, kita dapat mengatakan bahwa percepatan a sebanding dengan vektor normal permukaan n dibagi dengan massa partikel.


di mana k adalah konstanta proporsionalitas, dan m adalah massa partikel. Jika massa sama dengan volume dikalikan dengan kepadatan, maka kita memperoleh sistem gerak partikel lengkap menggunakan mekanika klasik:

//... particle "drop" was spawned above at random position

glm::ivec2 ipos = drop.pos; //Floored Droplet Initial Position
glm::vec3 n = surfaceNormal(ipos.x, ipos.y);  //Surface Normal

//Accelerate particle using classical mechanics
drop.speed += dt*glm::vec2(n.x, n.z)/(drop.volume*density);
drop.pos   += dt*drop.speed;
drop.speed *= (1.0-dt*friction);  //Friction Factor

//...

Catatan: kecepatan setelah gerakan partikel dikurangi oleh vektor gesekan. Perhatikan bahwa faktor langkah waktu termasuk di sini. Partikel memiliki inersia sendiri, sebanding dengan kepadatannya karena fakta bahwa kita mensimulasikan gerakan mereka menggunakan akselerasi.

Proses pembentukan batuan sedimen: transfer massa


Proses pembentukan batuan sedimen secara fisik terjadi sebagai transfer batuan sedimen dari bumi ke partikel dan kembali ke titik partikel (" transfer massa ").

Dalam teknologi kimia, perpindahan massa (mis., Perubahan massa / sedimen dari waktu ke waktu) antara dua fase (dalam hal ini, permukaan bumi dan tetesan) biasanya digambarkan menggunakan koefisien perpindahan massa .

Transfer massa sebanding dengan perbedaan antara konsentrasi c dan konsentrasi keseimbangan c_eq:


di mana k adalah konstanta proporsionalitas (koefisien perpindahan massa). Perbedaan antara keseimbangan dan konsentrasi aktual ini sering disebut sebagai "kekuatan pendorong."

Jika konsentrasi kesetimbangan lebih tinggi dari arus, maka partikel tersebut menyerap batuan sedimen. Jika lebih rendah, maka kehilangan mereka. Jika mereka sama, maka tidak ada perubahan yang akan terjadi.

Koefisien perpindahan massa dapat diartikan dengan berbagai cara:

  • Sebagai frekuensi transisi antar fase (ini dia "laju deposisi")
  • Tingkat di mana konsentrasi tetesan cenderung ke konsentrasi kesetimbangan

Sistem ini sepenuhnya tergantung pada penentuan konsentrasi kesetimbangan. Bergantung pada definisi, sistem akan menunjukkan berbagai dinamika pengendapan batuan sedimen. Dalam implementasi saya, konsentrasi kesetimbangan lebih tinggi jika kita bergerak ke bawah, dan jika kita bergerak lebih cepat, dan juga sebanding dengan volume partikel:

//...

//Compute Equilibrium Sediment Content
float c_eq = drop.volume*glm::length(drop.speed)*(heightmap[ipos.x][ipos.y]-heightmap[(int)drop.pos.x][(int)drop.pos.y]);

if(c_eq < 0.0) c_eq = 0.0;

//Compute Capacity Difference ("Driving Force")
float cdiff = c_eq - drop.sediment;

//Perform the Mass Transfer!
drop.sediment += dt*depositionRate*cdiff;
heightmap[ipos.x][ipos.y] -= dt*drop.volume*depositionRate*cdiff;

//...

Catatan: perubahan konsentrasi di dalam partikel sepenuhnya dijelaskan oleh persamaan transfer massa. Perubahan dalam peta ketinggian juga dikalikan dengan volume partikel, karena kami mengubahnya secara proporsional bukan untuk konsentrasi, tetapi untuk massa (konsentrasi dikalikan dengan volume).

Aspek lainnya


Peta ketinggian diinisialisasi oleh noise Perlin multi-layer dengan seed acak.

Pada akhir setiap langkah waktu, partikel kehilangan sedikit massa sesuai dengan laju penguapan:

//...

drop.volume *= (1.0-dt*evapRate);

//...

Proses ini diulangi untuk ribuan partikel yang dibuat di tempat-tempat acak dan disimulasikan secara terpisah (dalam kasus saya, perhitungan dilakukan secara berurutan dalam CPU).

Implementasi default saya mencakup seperangkat parameter yang baik. Setelah 200 ribu partikel, erosi terlihat sangat baik.

hasil


Kode selesai untuk proses erosi sekitar 20 baris tanpa komentar.

Berikut ini adalah perbandingan "sebelum dan sesudah" untuk 10 sampel. Simulasi ini menghasilkan punggungan yang sangat indah di ketinggian, batuan sedimen diendapkan di sisi beberapa punggungan, yang mengarah pada penciptaan dataran tinggi yang indah.


Pilihan sepuluh perbandingan sebelum dan sesudah. Shader yang saya tulis menerima dua warna pada input. Saya juga menerapkan pemetaan bayangan, kabut tergantung jarak dan bayangan Phong.

Berikut ini sepuluh sampel (berbeda) hanya dengan hasilnya:


Sepuluh hasil sampel lagi. Mereka berbeda dari yang sebelumnya, bahkan jika beberapa formasi terlihat serupa.

Dengan memilih seed berbeda selama inisialisasi peta, Anda dapat membuat hasil berbeda yang dikontrol.

Waktu simulasi


Waktu simulasi berhubungan langsung dengan masa hidup partikel dan jumlah partikel yang disimulasikan.

Beberapa faktor mempengaruhi kehidupan partikel, dan itu dapat sangat bervariasi untuk setiap partikel, karena mereka dibuat di tempat acak:

  • Gesekan dan inersia: kecepatan partikel
  • Ukuran Kisi: Kemungkinan partikel akan jatuh dari peta.
  • Tingkat penguapan: tingkat kepunahan partikel

Dengan parameter default, simulasi partikel individu membutuhkan 10-100 milidetik, yang menghasilkan 10-20 detik untuk simulasi 200.000 partikel.

Anda dapat meningkatkan tingkat erosi dan mengurangi usia partikel dengan meningkatkan langkah waktu tanpa mengubah jumlah partikel yang disimulasikan. Ini dapat membuat simulasi lebih β€œberisik”, dan jika langkah waktunya terlalu besar, ada kemungkinan simulasi akan gagal.

Simulasi itu sendiri di mesin mengeluarkan biaya tambahan untuk menciptakan kembali mesh permukaan untuk rendering.

Anda dapat mengoptimalkan kode dengan mengurangi biaya pembuatan kembali mesh atau dengan meningkatkan kecepatan satu langkah waktu untuk partikel individu.

Bekerja untuk masa depan


Segera saya akan memasukkan kode ini ke proyek Territory saya sebagai dasar untuk menghasilkan peta ketinggian di generator elevasi.

Saya sudah menulis kerangka kerja untuk simulasi dinamika fluida yang disederhanakan dalam sistem iklim, tetapi belum siap untuk dipublikasikan. Sistem ini mendapatkan pola iklim dari peta ketinggian. Ini akan menjadi topik untuk postingan mendatang tentang sistem iklim prosedural yang akurat secara fisik!

Dengan menggunakan sistem iklim yang disimulasikan, di masa mendatang akan dimungkinkan untuk mengambil sampel partikel dari distribusi (misalnya, di tempat-tempat hujan) daripada mendistribusikannya secara merata di peta. Mereka akan secara ideal dikombinasikan dengan geologi dan iklim bantuan.

Selain itu, setelah menambahkan berbagai jenis formasi geologi, batu dapat memiliki tingkat kelarutan yang berbeda. Ini akan secara langsung mempengaruhi koefisien perpindahan massa (laju deposisi), menciptakan laju erosi yang berbeda.

Sistem ini tidak dapat mensimulasikan fluida nyata dan aliran sungai, tetapi berpotensi dapat disesuaikan dengan tugas-tugas seperti itu. Saya akan memikirkannya dan mungkin di masa depan saya akan merilis kelanjutan pos.

All Articles