Cách xác định xem phòng dựa trên voxel 3D có được niêm phong, hiệu quả không


10

Tôi đã gặp một số vấn đề với việc xác định hiệu quả nếu các phòng lớn được niêm phong trong phòng 3D dựa trên voxel. Tôi đang ở một thời điểm mà tôi đã cố gắng hết sức để giải quyết vấn đề mà không cần sự giúp đỡ, nhưng không cố gắng đủ để từ bỏ, vì vậy tôi đang yêu cầu sự giúp đỡ.

Để làm rõ, niêm phong rằng không có lỗ trong phòng. Có máy hàn oxy, kiểm tra xem phòng có bịt kín không, và niêm phong tùy thuộc vào mức độ oxy.

Ngay bây giờ, đây là cách tôi đang làm:

  • Bắt đầu từ khối phía trên gạch niêm phong (lỗ thông hơi nằm trên mặt trên của miếng bịt), vòng lặp đệ quy qua tất cả 6 hướng liền kề
  • Nếu gạch liền kề là một gạch đầy đủ, không chân không, tiếp tục qua vòng lặp
  • Nếu gạch liền kề không đầy hoặc là gạch chân không, hãy kiểm tra xem các khối liền kề đó có, đệ quy không.
  • Mỗi lần kiểm tra một lát, giảm một bộ đếm
  • Nếu số đếm bằng 0, nếu khối cuối cùng liền kề với gạch chân không, hãy trả lại rằng khu vực đó không được niêm phong
  • Nếu số đếm chạm 0 và khối cuối cùng không phải là khối chân không hoặc vòng lặp đệ quy kết thúc (không có gạch chân không nào) trước khi bộ đếm bằng 0, khu vực được niêm phong

Nếu khu vực không được niêm phong, hãy chạy lại vòng lặp với một số thay đổi:

  • Kiểm tra các khối liền kề cho gạch "không khí thoáng khí" thay vì gạch chân không
  • Thay vì sử dụng bộ đếm giảm dần, hãy tiếp tục cho đến khi không tìm thấy gạch "không khí dễ thở" liền kề nào.
  • Khi vòng lặp kết thúc, đặt từng khối được kiểm tra thành một khối chân không.

Đây là mã tôi đang sử dụng: http://pastebin.com/NimyKncC

Vấn đề:

Tôi đang chạy kiểm tra này cứ sau 3 giây, đôi khi một người niêm phong sẽ phải vòng qua hàng trăm khối và một thế giới rộng lớn với nhiều máy hàn oxy, những vòng lặp đệ quy này cứ sau vài giây có thể rất khó khăn với CPU.

Tôi đã tự hỏi nếu bất cứ ai có nhiều kinh nghiệm hơn với tối ưu hóa có thể giúp tôi, hoặc ít nhất là chỉ cho tôi đi đúng hướng. Cảm ơn nhiều.


Chỉ kiểm tra khi mọi thứ thay đổi sẽ là một sự khởi đầu. Kiểm tra cứ sau ba giây có vẻ như quá mức cần thiết, vì bạn biết khi nào voxels thay đổi có thể phá vỡ phong ấn. Nếu một voxel tạo nên một căn phòng kín bị thay đổi, bạn có thể đánh dấu căn phòng đó để kiểm tra lại, nếu không, đừng bận tâm.
MichaelHouse

Vì có thể có hàng trăm voxels thay đổi trong khung thời gian 3 giây đó, tôi nghĩ sẽ hiệu quả hơn nếu chỉ làm theo định kỳ thay vì kiểm tra xem có gì đó đã thay đổi gần đó không. Tôi sẽ thử nghiệm với điều đó mặc dù.
NigelMan1010

Ồ, nếu hàng trăm voxels có thể thay đổi trong khung thời gian 3 giây, bạn có thể sẽ gặp một số vấn đề với hiệu suất. Bắt đầu định hình mã của bạn để tìm sự thiếu hiệu quả. Chúc may mắn!
MichaelHouse

Câu trả lời:


3

Giải pháp tốt nhất sẽ dựa vào nhiều yếu tố, như kích thước phòng dự kiến.

  1. Chỉ làm điều này kiểm tra, khi một cái gì đó thực sự thay đổi.

Cách tiếp cận 1:

Bạn có thể sử dụng A * để tìm đường dẫn từ lỗ thông hơi đến ô phía trên lỗ thông hơi / lỗ thông hơi hoặc đến một ô được gọi là vắc-xin. Nếu đường dẫn được tìm thấy, phòng không được tiết lộ. Điều này không quá khác biệt so với cách tiếp cận hiện tại của bạn nhưng nên nhanh hơn. Sau khi tìm thấy, tạo một "vùng lũ" để đặt gạch dưới dạng chân không.

Cách tiếp cận 2:

Có thể cấu trúc bên ngoài của bạn ít phức tạp hơn - xem xét, có một bề mặt là các phòng, bạn không cần phải di chuyển theo tất cả 6 hướng, vì vậy bạn nên đi dọc theo bề mặt, đánh dấu mỗi ô là chân không mà bạn di chuyển.


0

Khi bạn thực hiện tìm kiếm đệ quy, bạn có chắc chắn rằng bạn không kiểm tra cùng một voxel nhiều lần không? Tôi không thể nói từ cách bạn mô tả thuật toán của mình, nhưng bạn nên có một loại cờ nào đó để cho biết liệu bạn đã mở rộng đệ quy một voxel chưa, vì vậy bạn không nên làm điều đó nhiều lần.

Và như Byte56 đã nói, bạn cũng chỉ nên kiểm tra rò rỉ khi mọi thứ thay đổi. Điều đó có thể giảm thiểu đáng kể số lượng công việc bạn làm, tùy thuộc vào tần suất thay đổi xảy ra. Bạn thậm chí có thể lưu trữ thông tin giữa các cuộc gọi liên tiếp đến thuật toán, điều này có thể tầm thường hóa số lượng tính toán bạn thực hiện sau cuộc gọi đầu tiên.

Biên tập:

Tôi đã xem một số mã của bạn. Có vẻ như bạn đang sử dụng LinkedList để cho biết liệu voxel đã được kiểm tra chưa, như trong đoạn đầu tiên của tôi. Bạn có thể có kết quả tốt hơn nếu bạn sử dụng một cái gì đó ngoài LinkedList cho việc này. Có lẽ hãy thử một Hashset hoặc một cái gì đó? Điều này sẽ làm giảm độ phức tạp của phương thức kiểm tra của bạn từ O (n) đến O (1).


Có, tôi đang thêm nó vào LinkedList có tên là "đã kiểm tra", rồi kiểm tra xem danh sách đó có chứa vị trí hay không trước khi kiểm tra nó. Tôi nghĩ rằng việc kiểm tra nếu một cái gì đó thay đổi cũng sẽ cực kỳ tốn CPU, vì hàng trăm voxels có thể đã thay đổi trong khoảng thời gian 3 giây đó. Mặc dù vậy, tôi sẽ thấy một hashset so sánh với danh sách liên kết trong tình huống này, cảm ơn.
NigelMan1010
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.