Tôi đang cố gắng triển khai hệ thống tạo địa hình dựa trên voxel trong Unity3d (C #). Tôi đã thực hiện thành công một hệ thống lưới 3d thống nhất và đã trích xuất phần bề mặt bằng cách sử dụng thuật toán Marching Cubes và Surface Nets.
Tôi nhanh chóng gặp phải các vấn đề cố hữu trong việc thể hiện tất cả không gian bằng lưới 3d. Phần lớn không gian này ở trên hoặc dưới bề mặt, và tôi chuyển sang phân vùng không gian bằng octrees, vì nó dường như không quá khó khăn. Một trong những điều tuyệt vời về octrees là các nút octree không có các cạnh được giao nhau bởi bề mặt không cần phải phân chia lại.
Tôi đã nghiên cứu và tìm thấy một vài tài nguyên để xây dựng mã của mình. Một là Volume GFX , và một cái khác là bài viết Đường viền kép gốc của Ju et al. Việc kiểm tra cạnh của tôi được thực hiện bằng cách kiểm tra của Marching Cube từ mã của Paul Bourke. Nếu "cubeindex" là 0 hoặc 255, thì không có cạnh nào được giao nhau và nút octree không cần phải phân tách.
Mã thế hệ Octree của tôi hoạt động cho một cái gì đó giống như một phần tư hình cầu, trong đó các tính năng bề mặt cực kỳ bình thường:
Như đã thấy trong hình, chỉ có các nút octree chứa bề mặt được chia nhỏ. Làm việc tuyệt vời.
Tuy nhiên, bây giờ, khi chúng ta chuyển sang một thứ phức tạp hơn, như hàm PerlinNiri của Unity3d: GASP ! Cái lỗ đó đang làm gì trong lưới ở góc dưới bên phải? Khi kiểm tra kỹ hơn, chúng ta thấy octree không chia nhỏ đúng cách (các đường màu đỏ làm nổi bật kích thước của nút vi phạm): Điều này hóa ra cũng là vấn đề tương tự Jules Bloomenthal trong bài viết về đa giác hóa , trang 10, Hình 10. Phương pháp truyền thống khi tạo octrees từ trên xuống ("Phân khu thích ứng"), rất nhạy cảm với các đặc điểm bề mặt mịn so với kích thước của nút octree.
Ý chính
X-------X
| |
| | <- Node
X--/\---X X's - tested values, all outside of the surface!
/ \ <- surface
Bề mặt phá vỡ bề mặt, nhưng quay trở lại trước khi nó đi qua một đỉnh. Bởi vì chúng tôi tính toán các giao điểm cạnh bằng cách nhìn vào các dấu hiệu ở hai đỉnh, điều này không đánh dấu cạnh là giao nhau.
Có phương pháp nào để xác định xem những dị thường này có tồn tại không? Tốt hơn là, giải pháp sẽ hoạt động không chỉ cho chức năng nhiễu Unity3d, mà còn cho bất kỳ chức năng nhiễu 3d nào (đối với vách đá / phần nhô ra / đảo nổi, v.v.).
CẬP NHẬT
Nhờ câu trả lời tuyệt vời của Jason, tôi đã có thể trả lời các câu hỏi của riêng mình mà tôi đã hỏi (trong các bình luận dưới câu trả lời của anh ấy). Vấn đề tôi gặp phải là tôi đã không hiểu làm thế nào tôi có thể tạo ra một hàm giới hạn cho các hàm lượng giác (sin, cos, v.v.) do tính chất định kỳ của chúng.
Đối với những người này, tính định kỳ là chìa khóa cho các chức năng giới hạn. Chúng tôi biết rằng sin / cos đạt đến các giá trị cực trị của chúng trong một khoảng thời gian xác định, cụ thể là mỗi π/2
. Vì vậy, nếu khoảng thời gian chúng tôi đang kiểm tra có chứa bất kỳ bội số (cos) hoặc nửa bội số (sin) hơn 1 / -1 là cực trị nhất định. Nếu nó không chứa bội số (tức là khoảng [0.1,0.2]
), thì phạm vi chỉ đơn giản là các giá trị của hàm được đánh giá tại các điểm cuối của nó.
CẬP NHẬT 2:
Nếu những điều trên không có ý nghĩa, hãy kiểm tra câu trả lời của Jason cho ý kiến của tôi.