복셀 지형을 나타내는 데 어떤 데이터 구조를 사용해야합니까?


18

복셀에 관한 Wikipedia 페이지 에 따르면 , "[...] 복셀의 위치는 다른 복셀에 대한 위치 (즉, 단일 체적 이미지를 구성하는 데이터 구조에서의 위치)에 기초하여 추론됩니다."

그러한 데이터 구조를 어떻게 구현해야합니까? 나는 octree에 대해 생각하고 있었지만 내가 들어 본 적이없는 것이 있는지 궁금합니다.


1
복셀 데이터에 필요한 데이터에 따라 달라지기 때문에 질문하기가 다소 어렵습니다. 복셀이 얼마나 가득 찼는 지, 어떻게 생겼는지 등과 같은 것들이 당신이하는 일에 상당히 의존적입니다. 둘째, 데이터 구조는 데이터의 실시간 조작 및 후속 업데이트를 위해 고속 액세스에 적합해야합니다. 복셀 당 메모리 구조를 낮게 유지하는 방법과 데이터 빠른 액세스 / 조작을 빠르게하는 방법은 주요 기술 과제입니다. 복셀 엔진으로 작업 할 때 상당히 의도적입니다. 답이 아니므로 의견.
제임스

답변:


14

먼저. 각 복셀에 대해 알고있는 내용을 작성해 봅시다.

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

일반 보관

일반적인 방법은 간단합니다.

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

복셀이 공간에 있고 두 지점이 한 곳을 차지할 방법이 없기 때문에 삼중 항 (x, y, z)은 각 복셀을 고유하게 식별합니다. 정적 복셀 데이터에 대해 이야기하고 있다고 생각합니다.

간단한 데이터에는 적합합니다. 그러나 결코 빠른 데이터 구조는 아닙니다.

렌더링은 스캔 라인 알고리즘으로 수행되는 AFAIK입니다. 복셀에 관한 Tom의 하드웨어 기사에는 scanline algorithm 이미지가 있습니다.

빠른 조회

빠른 조회가 필요한 경우 조회를위한 가장 빠른 데이터 구조는 해시 (일명 배열, 맵 ...)입니다. 따라서 해시를 만들어야합니다. 따라서 순진하게 우리는 임의의 요소를 얻는 가장 빠른 방법을 원합니다.

array [x][y][z] of (color)
  • x, y, z 좌표로 복셀을 찾는 O (1)이 있습니다.

  • 문제는 공간 요구 사항이 O (D ^ 3)이고 여기서 D는 각 x, y 및 z 숫자의 범위입니다 (256 개의 범위를 갖는 Chars 인 경우 256을 곱하기 때문에 실수를 잊어 버립니다). 3 = 2 ^ 24 == 16 777 216 배열).

그러나 그것은 복셀로하고 싶은 것에 달려 있습니다. 렌더링이 원하는 것이라면 아마도이 배열 일 것입니다. 그러나 스토리지 문제는 여전히 남아 있습니다 ...

스토리지가 문제인 경우

한 가지 방법은 어레이에서 RLE 압축을 사용하는 것입니다. 복셀 슬라이스 (복셀 세트, 여기서 복셀은 하나의 좌표 상수 값을가집니다. 예를 들어 z = 13 인 평면과 같은)를 상상해보십시오. 이러한 복셀 조각은 MSPaint의 간단한 그림처럼 보입니다 . Voxel 모델은 일반적으로 가능한 모든 장소의 일부를 차지합니다 (모든 가능한 복셀의 D ^ 3 공간). "삼중 좌표에서 한 쌍을 가져 와서 나머지 축을 압축하십시오"는 트릭을 수행한다고 생각합니다 (예 : [x] [y]를 취하고 각 요소에 대해 주어진 x, y에서 z 축의 모든 복셀을 압축합니다 .. 0에서 몇 개의 요소가 있어야하며 RLE는 여기에서 잘 작동합니다).

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

스토리지 문제를 해결하는 다른 방법은 트리 데이터 구조를 사용하는 배열 대신입니다.

tree data structure  = recursively classified voxels
for octrees: recursively classified by which octant does voxel at (x,y,z) belong to
  • Nick이 언급 한 Octree. 복셀을 압축해야합니다. Octree는 조회 속도가 적당합니다 .N은 복셀 수인 O (log N)입니다.
  • Octree는 적절한 임의의 복셀 데이터를 저장할 수 있어야합니다.

복셀이 단순한 하이트 맵이라면 그냥 저장할 수 있습니다. 또는 하이트 맵을 생성하는 함수, 즉 절차 적으로 생성하는 매개 변수를 저장할 수 있습니다.

물론 모든 가능한 접근 방식을 결합 할 수 있습니다. 그러나 코드가 작동하는지 테스트하고 코드가 실제로 더 빠르다는 것을 측정하지 않으면 과도하게 사용하지 마십시오 (최적화 가치가 있음).

TL; DR

Octrees 이외에 voxels, Google "voxlap", "ken silverman"을 사용한 RLE 압축은 ...

자원

목록이 빠르고, 복셀 렌더링을 서류와 소스 코드를 포함하는 방법에 대한 리소스와 토론 .


1
"저장에 문제가있는 경우": 또한 VTC ( oss.sgi.com/projects/ogl-sample/registry/NV/… ) 또는 DXT 압축을 사용할 수 있습니다
KindDragon

@KindDragon이 정보에 감사드립니다. :) 아주 좋은 생각입니다.
user712092

리소스 링크가 다운되었습니다.
Ezequiel

4

그들이 이야기하고있는 두 가지 다른 데이터 구조 측면이 있습니다.

배열 구조

여러 차원의 배열 요소를 참조 할 때 일단 색인 (예 :)을 전달하면 myArray[4][6][15]해당 위치에 무엇이 있는지 알고 배열 자체를 고려하십시오 . 해당 위치에있는 것이 복셀 인 경우, 해당 복셀은 자신의 x, y 및 z 좌표를 추가로 기록 할 필요가 없습니다. 복셀을 보유한 배열은 배열 색인 위치에 따라 암시 적으로 세계 위치를 지정합니다.

이것이 좋은 이유는 이런 종류의 배열 액세스에 사용되는 포인터 산술이 본질적으로 빠르며 일반적으로 말해서 언어 전체에서 발견되는 대부분의 빠른 (종종 "기본") 배열의 기초를 제공하기 때문입니다. 이러한 배열의 단점은 포인터 산술을 적용 할 수 있도록 동일한 크기의 요소를 바이트 단위로 가져야한다는 것입니다.

옥트리

(이것은 위키 백과가 언급하는 것보다 적기 때문에이 두 번째에 주목하며, 거의 모든 현대적인 것들이 octree를 사용하지만 복셀 구현은 octree를 사용할 필요가 없습니다.)

octree의 루트 노드는 하나의 분할되지 않은 큐브입니다. 예를 들어 봅시다. 큐브의 중심 인 옥트리의 루트 {0, 0, 0}가 3D 공간에 있다고 가정하십시오 . 해당 공간 내에 객체를 배치하기 시작하면 (읽기 : 둘 이상의 객체) 이제 octree를 더 세분화해야합니다. 여기서는 3 개의 평면을 사용하여 분할하여 8 ( oct- ) 로 나누는 곳입니다. 이 평면은 xy, xz 및 yz 평면입니다. 원래 큐브에는 정확히 8 개의 작은 큐브가 포함됩니다. 이러한 각 하위 노드는 중앙의 부모 큐브에서 오프셋으로 배치됩니다 . 즉, 예를 들어, 양의 xyz 옥탄트에 놓인 큐브는 정확히 /의 큐브 중심을 포함하는 부모와의 오프셋을 갖습니다.{root.width / 4, root.height / 4, root.depth / 4}. 각 하위 노드에 대한 절대 위치를 지정하는 대신 부모 노드를 자식 공간의 원점으로 간주하는 것이 더 논리적입니다. 이것은 장면 그래프가 작동하는 것과 같은 방식입니다.

정사각형을 그리고 4 개의 동일한 영역으로 세분화하는 2D 도면에서이를 쉽게 볼 수 있습니다. octree 루트 노드와 같이 부모 사각형의 중심이로 간주 {0, 0}되면 자식 사각형의 4 개의 중심은

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

... 부모와 관련하여-3D와 동일한 원칙.


답변 주셔서 감사합니다. 필자의 경우 지형의 일부는 같은 유형의 복셀로 만들어 졌기 때문에 옥트리에 대해 생각한 것입니다 (큰 덩어리를 세분화하지 않아도 됨). 그러나 구현하기가 더 단순 해 보이기 때문에 3D 배열에 대해 설명하겠습니다. 필자는 터 레인 클래스의 구현 세부 사항을 충분히 추상화하여 구현을 전환하는 것이 어렵지 않게 할 수 있다고 확신합니다.
pwny

천만에요. 나는 확실히 octree를 살펴볼 것을 제안 할 것입니다. 실제로 그들은 이해하기 어렵지 않습니다. 그러나 그렇습니다. 현재 3D 어레이를 사용하여 초기 프로토 타이핑을 수행하는 것이 좋습니다.
엔지니어

더 읽어 보면 인텔의 게임용 STL 확장 기사 에서 몇 가지 유용한 참조를 포함한 옥트리 구현에 대한 적절한 설명을 찾을 수 있습니다 .
Martin Foot

1

RLE을 사용할 수 있습니다. 그러나 SVO (Sparse Voxel Octree)를 사용할 수 있으며 id Tech 6은 SVO를 사용합니다. SVO는 옥트리 데이터 표현에 대한 레이 캐스팅 또는 레이 트레이싱 접근 방식을 사용하는 3D 컴퓨터 그래픽 렌더링 기술입니다.

이 기술은 다소 다양하지만 일반적으로 화면의 해상도와 크기에 따라 표시되거나 표시 될 수있는 선체 지점 (스파 스 복셀)의 생성 및 처리에 의존합니다.

더 빠르기 때문에 레이 캐스팅을 사용하십시오.


0

일반적으로 지형에 대한 3D 데이터 구조를 피할 수 있습니다. 대신 하이트 맵을 사용할 수 있습니다 . 이것은 런타임에 매우 저렴하고 효율적으로 복셀 될 수 있습니다. 일반적으로 (내 경험상) 각 열에서 렌더링 해야하는 최소 높이를 추적하고 때로는 시작-정지 각도를 추적하여 후면 열을 컬링 할 수 있습니다.

내가 오랫동안 돌아간 것입니다 : http://sites.google.com/site/williamedwardscoder/spinning-voxels-in-flash

지형에 하이트 맵으로 표현할 수없는 돌출부 나 동굴 또는 기타 지형지 물이 적은 경우, 하이트 맵에 구멍이 생길 수 있으며 런타임 비용이 드는 현지화 된 장소를 채우는 진정한 3D 복셀 객체와 같은 대체 표현이 가능합니다 보증됩니다.

희귀 복셀 표현 은 큰 실제 복셀 세계가있을 때 가치가 있습니다. 존 카맥 (John Carmack) 은 지난 몇 년 동안 그들에게 이야기 해 왔습니다 ...


하이트 맵에 대해서도 생각했지만 몇 가지가 나를 멀리했습니다. 내 경우에는 지형이 어떤 식 으로든 크지 않거나 매우 복잡하지 않습니다 (미로 유형 지형, 매우 직교). 또한 지형의 일부를 파괴 가능하게 만들거나 사용자가 건설을 통해 지형에 영향을 줄 수 있기를 바랍니다. 이로 인해 플레이어는 지형에서 "터널"을 생성하여 하이트 맵으로 표현하기가 더 복잡해 보일 수 있습니다.
pwny
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.