Cara menentukan apakah ruang berbasis voxel 3D disegel, secara efisien

10

Saya telah mengalami beberapa masalah dengan menentukan secara efisien apakah kamar besar disegel dalam ruang 3D berbasis voxel. Saya pada titik di mana saya telah berusaha sekuat tenaga untuk menyelesaikan masalah tanpa meminta bantuan, tetapi tidak mencoba cukup untuk menyerah, jadi saya meminta bantuan.

Untuk memperjelas, disegel adalah bahwa tidak ada lubang di ruangan. Ada sealer oksigen, yang memeriksa apakah ruangan disegel, dan segel tergantung pada tingkat input oksigen.

Saat ini, inilah yang saya lakukan:

  • Mulai dari blok di atas ubin sealer (lubang ada di wajah atas sealer), secara loop berulang melalui semua 6 arah yang berdekatan
  • Jika ubin yang berdekatan penuh, non-vakum, lanjutkan melalui loop
  • Jika ubin yang berdekatan tidak penuh, atau merupakan ubin vakum, periksa apakah blok yang berdekatan adalah, secara rekursif.
  • Setiap kali ubin dicentang, kurangi penghitung
  • Jika penghitungan mencapai nol, jika blok terakhir berbatasan dengan ubin vakum, kembalikan bahwa area tersebut tidak disegel
  • Jika penghitungan mencapai nol dan blok terakhir bukan ubin vakum, atau loop rekursif berakhir (tidak ada ubin vakum tersisa) sebelum penghitung adalah nol, area disegel

Jika area tidak disegel, jalankan loop lagi dengan beberapa perubahan:

  • Memeriksa blok yang berdekatan untuk ubin "udara bernapas" bukan ubin vakum
  • Alih-alih menggunakan penghitung pengurangan, lanjutkan sampai tidak ada ubin "udara bernafas" yang berdekatan ditemukan.
  • Setelah loop selesai, atur setiap blok yang dicentang ke ubin vakum.

Berikut kode yang saya gunakan: http://pastebin.com/NimyKncC

Masalah:

Saya menjalankan pemeriksaan ini setiap 3 detik, kadang-kadang sealer harus melewati ratusan blok, dan sebuah dunia besar dengan banyak sealer oksigen, beberapa loop rekursif ini setiap beberapa detik bisa sangat sulit pada CPU.

Saya bertanya-tanya apakah ada orang yang lebih berpengalaman dengan optimasi dapat membantu saya, atau setidaknya mengarahkan saya ke arah yang benar. Terima kasih banyak.

NigelMan1010
sumber
Hanya memeriksa ketika segalanya berubah akan menjadi awal. Memeriksa setiap tiga detik sepertinya berlebihan, karena Anda tahu kapan voxel berubah yang dapat merusak segel. Jika voxel yang membentuk ruang tertutup diubah, Anda dapat menandai ruangan itu untuk diperiksa ulang, jika tidak, jangan repot-repot.
MichaelHouse
Karena mungkin ada ratusan voxel yang diubah dalam jangka waktu 3 detik itu, saya pikir akan lebih efisien untuk melakukannya secara berkala daripada memeriksa apakah ada sesuatu yang berubah di sekitarnya. Saya akan bereksperimen dengan itu.
NigelMan1010
Oh, yah jika ratusan voxel dapat berubah dalam kerangka waktu 3 detik, Anda mungkin akan memiliki sejumlah masalah dengan kinerja. Mulai membuat profil kode Anda untuk menemukan inefisiensi. Semoga berhasil!
MichaelHouse

Jawaban:

3

Solusi terbaik akan bergantung pada banyak faktor, seperti ukuran ruangan yang diharapkan.

  1. Hanya lakukan pemeriksaan ini, ketika ada sesuatu yang benar-benar berubah.

Pendekatan 1:

Anda dapat menggunakan A * untuk menemukan jalur dari lubang angin ke ubin di atas lubang angin / lubang angin itu sendiri atau ke ubin yang dikenal sebagai vaccum. Jika jalur ditemukan, kamar tidak tertutup. Ini tidak jauh berbeda dari pendekatan Anda saat ini tetapi harus lebih cepat. Setelah ditemukan, buat "fill banjir" untuk mengatur ubin sebagai ruang hampa.

Pendekatan 2:

Mungkin struktur luar Anda kurang pas - mengingat, bahwa ada permukaan di mana kamar-kamarnya, Anda tidak perlu bergerak ke semua 6 arah, jadi Anda harus melakukan perjalanan sepanjang permukaan, tandai setiap ubin sebagai ruang hampa udara yang Anda bawa.

reiti.net
sumber
0

Saat Anda melakukan pencarian berulang, apakah Anda memastikan Anda tidak memeriksa voxel yang sama beberapa kali? Saya tidak tahu dari cara Anda mendeskripsikan algoritma Anda, tetapi Anda harus memiliki semacam flag untuk menunjukkan apakah Anda telah memperluas voxel secara rekursif, jadi Anda tidak melakukannya lebih dari sekali.

Dan seperti dikatakan Byte56, Anda juga harus memeriksa kebocoran ketika ada perubahan. Itu bisa sangat meminimalkan jumlah pekerjaan yang Anda lakukan, tergantung pada seberapa sering perubahan terjadi. Anda bahkan dapat menyimpan informasi antara panggilan berurutan ke algoritme, yang dapat meremehkan jumlah perhitungan yang Anda lakukan setelah panggilan pertama.

Edit:

Saya melihat beberapa kode Anda. Sepertinya Anda menggunakan LinkedList untuk menunjukkan apakah voxel sudah diperiksa, seperti pada paragraf pertama saya. Anda mungkin memiliki hasil yang lebih baik jika Anda menggunakan sesuatu selain LinkedList untuk ini. Mungkin mencoba HashSet atau sesuatu? Ini harus mengurangi kompleksitas metode pemeriksaan Anda dari O (n) ke O (1).

Rumsey
sumber
Ya, saya menambahkannya ke LinkedList yang disebut "dicentang", dan kemudian memeriksa apakah daftar itu berisi posisi sebelum memeriksanya. Saya berpikir bahwa memeriksa apakah ada yang berubah juga akan menjadi sangat intensif CPU, karena ratusan voxel dapat berubah dalam periode waktu 3 detik itu. Saya akan melihat bagaimana hashset dibandingkan dengan linkedlist dalam situasi ini, terima kasih.
NigelMan1010