Cấu trúc dữ liệu nào nên được sử dụng để thể hiện địa hình voxel?


18

Theo trang Wikipedia về voxels, "[...] vị trí của một voxel được suy ra dựa trên vị trí của nó so với các voxels khác (nghĩa là vị trí của nó trong cấu trúc dữ liệu tạo nên một hình ảnh thể tích duy nhất)."

Làm thế nào nên thực hiện một cấu trúc dữ liệu như vậy? Tôi đã suy nghĩ về một quãng tám nhưng tôi tự hỏi liệu có điều gì khác mà tôi chưa bao giờ nghe nói tới.


1
Đây là một câu hỏi hơi khó để hỏi vì nó phụ thuộc rất nhiều vào dữ liệu mà dữ liệu voxel của bạn sẽ cần. Những thứ như voxel đầy đủ như thế nào, trông như thế nào, v.v ... sẽ phụ thuộc khá nhiều vào những gì bạn đang làm. Thứ hai, cấu trúc dữ liệu phải cho phép truy cập tốc độ cao để thao tác dữ liệu theo thời gian thực và cập nhật dữ liệu sau đó .. Làm thế nào để giữ cấu trúc bộ nhớ ở mức thấp trên mỗi voxel và truy cập / thao tác nhanh dữ liệu là những thách thức kỹ thuật quan trọng ý định khá cụ thể khi làm việc với động cơ voxel. Không phải là một câu trả lời, vì vậy một nhận xét.
James

Câu trả lời:


14

Đầu tiên. Hãy viết những gì chúng ta biết về mỗi voxel:

voxel = (x, y, z, color) // or some other information

Kho chung

Cách chung chỉ đơn giản là thế này:

set of voxels = set of (x,y,z, color)

Lưu ý, bộ ba đó (x, y, z) xác định duy nhất mỗi voxel, vì voxel là điểm trong không gian và không có cách nào hai điểm chiếm một vị trí (tôi tin rằng chúng ta đang nói về dữ liệu voxel tĩnh).

Nó sẽ tốt cho dữ liệu đơn giản. Nhưng nó không có nghĩa là một cấu trúc dữ liệu nhanh.

Kết xuất là AFAIK được thực hiện bằng thuật toán scanline. Bài viết về phần cứng của Tom trên voxels có hình ảnh của thuật toán scanline .

Tra cứu nhanh

Nếu cần tra cứu nhanh, thì cấu trúc dữ liệu nhanh nhất để tra cứu là hàm băm (còn gọi là mảng, bản đồ ...). Vì vậy, bạn phải làm cho băm ra khỏi nó. Vì vậy, ngây thơ, chúng tôi muốn cách nhanh nhất để có được yếu tố tùy ý:

array [x][y][z] of (color)
  • Điều này có O (1) để tra cứu voxel theo tọa độ x, y, z.

  • Vấn đề là, yêu cầu không gian của nó là O (D ^ 3), trong đó D là phạm vi của mỗi số x, y và z (quên số thực, vì nếu chúng là Chars, có phạm vi 256 giá trị, sẽ có 256 ^ 3 = 2 ^ 24 == 16 777 216 phần tử trong mảng).

Nhưng nó phụ thuộc vào những gì bạn muốn làm với voxels. Nếu kết xuất là những gì bạn muốn, thì đó có thể là mảng bạn muốn. Nhưng vấn đề lưu trữ vẫn còn ...

Nếu lưu trữ là vấn đề

Một phương pháp là sử dụng nén RLE trong mảng. Hãy tưởng tượng một lát voxels (tập hợp các voxels, trong đó voxels có một giá trị hằng số tọa độ .... như mặt phẳng trong đó z = 13 chẳng hạn). Những voxels như vậy sẽ trông giống như một bản vẽ đơn giản trong MSPaint . Mô hình Voxel, tôi muốn nói, thường chiếm một phần của tất cả các vị trí có thể (D ^ 3 không gian của tất cả các voxels có thể). Tôi tin rằng, "lấy một cặp từ bộ ba tọa độ và nén trục còn lại" sẽ thực hiện thủ thuật (ví dụ: lấy [x] [y] và cho mỗi phần tử nén tất cả các voxels tại trục z tại x, y .. nên có 0 đến vài yếu tố, RLE sẽ làm tốt ở đây):

array [x][y] of RLE compressed z "lines" of voxel; each uncompressed voxel has color 

Phương pháp khác để giải quyết vấn đề lưu trữ sẽ là thay vì sử dụng cấu trúc dữ liệu cây:

tree data structure  = recursively classified voxels
for octrees: recursively classified by which octant does voxel at (x,y,z) belong to
  • Octree, như được đề cập bởi Nick. Nó nên nén voxels. Octree thậm chí có một tốc độ khá tốt để tra cứu, tôi đoán đó là một số O (log N), trong đó N là số lượng voxels.
  • Octree có thể lưu trữ dữ liệu voxel tùy ý.

Nếu voxels là một số sơ đồ chiều cao đơn giản Bạn có thể lưu trữ chỉ đó. Hoặc Bạn có thể lưu trữ các tham số cho chức năng tạo sơ đồ chiều cao, hay còn gọi là tạo thủ tục ...

Và tất nhiên Bạn có thể kết hợp tất cả các phương pháp có thể. Nhưng đừng lạm dụng nó, trừ khi bạn kiểm tra rằng Mã của bạn hoạt động và đo lường rằng nó THỰC SỰ nhanh hơn (vì vậy nó đáng để tối ưu hóa).

TL; DR

Khác với Octrees là nén RLE với voxels, google "voxlap", "ken silverman" ...

Tài nguyên

Có danh sách các tài nguyên và thảo luận về cách tạo trình kết xuất voxel nhanh, bao gồm các giấy tờ và mã nguồn .


1
"Nếu lưu trữ là vấn đề": bạn cũng có thể sử dụng VTC ( oss.sgi.com/projects/ogl-sample/registry/NV/, ) hoặc nén DXT
KindDragon

@KindDragon cảm ơn bạn vì thông tin này. :) Đó là ý tưởng rất tốt.
dùng712092

Liên kết tài nguyên là xuống.
Ezequiel

4

Có hai khía cạnh cấu trúc dữ liệu khác nhau mà họ có thể nói đến.

Cấu trúc mảng

Khi bạn tham chiếu một phần tử của một mảng có số lượng kích thước bất kỳ, hãy xem xét rằng chính mảng đó, một khi bạn vượt qua các chỉ số (ví dụ myArray[4][6][15]) biết những gì ở vị trí đó. Nếu những gì ở vị trí đó là một voxel, thì voxel đó không cần phải ghi thêm tọa độ x, y và z của riêng nó - mảng giữ voxel chỉ định vị trí thế giới của nó dựa trên vị trí được lập chỉ mục theo mảng.

Lý do tốt là vì số học con trỏ được sử dụng cho loại truy cập mảng này vốn đã nhanh và nói chung, cung cấp nền tảng cho hầu hết các mảng nhanh (thường được gọi là "bản địa") được tìm thấy trên các ngôn ngữ. Nhược điểm của các mảng này là chúng phải có các phần tử có kích thước bằng nhau theo byte, để số học con trỏ nói trên được áp dụng.

Tháng mười

(Tôi lưu ý điều thứ hai này, vì đây ít có khả năng là những gì wikipedia đề cập đến và việc triển khai voxel không yêu cầu sử dụng octrees mặc dù gần như tất cả những người hiện đại đều sử dụng octrees.)

Nút gốc của octree là một khối đơn, không phân chia. Hãy thiết lập một ví dụ. Nói gốc của octree của bạn, trung tâm của khối lập phương, nằm {0, 0, 0}trong không gian 3D. Khi bạn bắt đầu đặt các đối tượng trong không gian đó (đọc: nhiều hơn một đối tượng), đã đến lúc chia nhỏ quãng tám hơn nữa. Đây là nơi bạn chia thành 8 ( oct- ), bằng cách cắt nó ra bằng 3 mặt phẳng, các mặt phẳng này là các mặt phẳng xy, xz và yz. Khối ban đầu của bạn bây giờ chính xác chứa 8 khối nhỏ hơn. Mỗi nút phụ này được định vị là phần bù từ khối chính, trung tâm . Đó là, ví dụ, khối lập phương nằm trong octant xyz dương sẽ có phần bù từ chính giữa / khối chứa chính xác của khối lập phương{root.width / 4, root.height / 4, root.depth / 4}. Thay vì chỉ định một vị trí tuyệt đối cho mỗi mã con, sẽ hợp lý hơn khi coi nút cha là nguồn gốc của không gian con của nó. Đây là cùng một cách làm việc đồ thị cảnh.

Nó đủ đơn giản để thấy điều này trong bản vẽ 2D, trong đó bạn vẽ một hình vuông và chia nó thành 4 vùng bằng nhau. Nếu, giống như nút gốc octree của chúng ta, trung tâm của hình vuông cha mẹ được coi là {0, 0}, thì 4 tâm của hình vuông con sẽ là

{root.width / 4, root.height / 4}, {-root.width / 4, root.height / 4}, {root.width / 4, -root.height / 4}, {-root.width / 4, -root.height / 4}

... Liên quan đến cha mẹ của họ - nguyên tắc giống như trong 3D.


Cảm ơn bạn vì câu trả lời. Trong trường hợp của tôi, một số phần lớn của địa hình sẽ được tạo ra từ cùng một loại voxel, đó là lý do tại sao tôi đã nghĩ về quãng tám (một đoạn lớn sẽ không phải chia nhỏ). Tuy nhiên, tôi sẽ cung cấp cho mảng 3D một shot vì nó trông đơn giản hơn để thực hiện. Tôi chắc chắn rằng tôi có thể quản lý để trừu tượng hóa các chi tiết triển khai của lớp địa hình của mình đủ để không quá khó để chuyển đổi các triển khai sẽ cần thiết.
pwny

Không có gì. Tôi chắc chắn sẽ đề nghị nhìn vào quãng tám, thực sự chúng không khó nắm bắt. Nhưng vâng, cách tiếp cận của bạn có ý nghĩa cho đến bây giờ, chắc chắn nó đáng để thực hiện tạo mẫu ban đầu bằng cách sử dụng một mảng 3D.
Kỹ sư

Khi đọc thêm, một cuộc thảo luận tốt về việc triển khai các quãng tám bao gồm một số tài liệu tham khảo hữu ích có thể được tìm thấy trong bài viết Mở rộng STL cho Trò chơi của Intel .
Martin Foot

1

Bạn có thể sử dụng RLE. Nhưng bạn có thể sử dụng SVO (Spzzy Voxel Octree), id Tech 6 sử dụng SVO. SVO là một kỹ thuật kết xuất đồ họa máy tính 3D bằng cách sử dụng phương pháp chiếu tia hoặc đôi khi là phương pháp dò tia thành biểu diễn dữ liệu quãng tám.

Kỹ thuật này có phần khác nhau, nhưng thường dựa vào việc tạo và xử lý vỏ của các điểm (voxels thưa thớt) có thể nhìn thấy hoặc có thể nhìn thấy được, dựa trên độ phân giải và kích thước của màn hình.

Sử dụng raycasting, vì nó nhanh hơn.


0

Nói chung, bạn có thể tránh cấu trúc dữ liệu 3D cho địa hình. Bạn có thể sử dụng một sơ đồ chiều cao thay thế. Điều này có thể được voxelised rất rẻ và hiệu quả trong thời gian chạy. Nó thường trả tiền (theo kinh nghiệm của tôi) để theo dõi chiều cao tối thiểu bạn cần để hiển thị trong mỗi cột và đôi khi cũng bắt đầu các góc bắt đầu để bạn cũng có thể loại bỏ các cột backface.

Đây là một cái tôi đã thực hiện từ lâu: http://sites.google.com.vn/site/williamedwardscoder/spinning-voxels-in-flash

Nếu địa hình của bạn có một số lượng nhỏ phần nhô ra hoặc hang động hoặc các tính năng khác không thể biểu thị bằng sơ đồ chiều cao, thì bạn có thể có các lỗ hổng trong sơ đồ chiều cao của mình và có một đại diện thay thế, ví dụ như các đối tượng voxel 3D thực sự chỉ lấp đầy những vị trí cục bộ nơi chi phí thời gian chạy Được bảo hành.

Các đại diện voxel thưa thớt có giá trị khi bạn có thế giới voxel thực sự lớn. John Carmack đã nói chuyện với họ trong vài năm qua ...


Tôi cũng nghĩ về chiều cao, nhưng một vài thứ đã đẩy tôi ra khỏi chúng. Vấn đề là trong trường hợp của tôi, địa hình không thực sự lớn bằng bất kỳ phương tiện nào hoặc rất phức tạp (nghĩ rằng một địa hình kiểu mê cung, rất cartesian). Tôi cũng muốn một phần của địa hình có thể bị phá hủy hoặc cho phép người dùng ảnh hưởng đến địa hình thông qua việc xây dựng. Điều này có thể dẫn đến việc người chơi tạo "đường hầm" trong địa hình có vẻ phức tạp hơn để thể hiện bằng sơ đồ chiều cao.
pwny
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.