복셀에 관한 Wikipedia 페이지 에 따르면 , "[...] 복셀의 위치는 다른 복셀에 대한 위치 (즉, 단일 체적 이미지를 구성하는 데이터 구조에서의 위치)에 기초하여 추론됩니다."
그러한 데이터 구조를 어떻게 구현해야합니까? 나는 octree에 대해 생각하고 있었지만 내가 들어 본 적이없는 것이 있는지 궁금합니다.
복셀에 관한 Wikipedia 페이지 에 따르면 , "[...] 복셀의 위치는 다른 복셀에 대한 위치 (즉, 단일 체적 이미지를 구성하는 데이터 구조에서의 위치)에 기초하여 추론됩니다."
그러한 데이터 구조를 어떻게 구현해야합니까? 나는 octree에 대해 생각하고 있었지만 내가 들어 본 적이없는 것이 있는지 궁금합니다.
답변:
먼저. 각 복셀에 대해 알고있는 내용을 작성해 봅시다.
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
복셀이 단순한 하이트 맵이라면 그냥 저장할 수 있습니다. 또는 하이트 맵을 생성하는 함수, 즉 절차 적으로 생성하는 매개 변수를 저장할 수 있습니다.
물론 모든 가능한 접근 방식을 결합 할 수 있습니다. 그러나 코드가 작동하는지 테스트하고 코드가 실제로 더 빠르다는 것을 측정하지 않으면 과도하게 사용하지 마십시오 (최적화 가치가 있음).
Octrees 이외에 voxels, Google "voxlap", "ken silverman"을 사용한 RLE 압축은 ...
그들이 이야기하고있는 두 가지 다른 데이터 구조 측면이 있습니다.
배열 구조
여러 차원의 배열 요소를 참조 할 때 일단 색인 (예 :)을 전달하면 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와 동일한 원칙.
RLE을 사용할 수 있습니다. 그러나 SVO (Sparse Voxel Octree)를 사용할 수 있으며 id Tech 6은 SVO를 사용합니다. SVO는 옥트리 데이터 표현에 대한 레이 캐스팅 또는 레이 트레이싱 접근 방식을 사용하는 3D 컴퓨터 그래픽 렌더링 기술입니다.
이 기술은 다소 다양하지만 일반적으로 화면의 해상도와 크기에 따라 표시되거나 표시 될 수있는 선체 지점 (스파 스 복셀)의 생성 및 처리에 의존합니다.
더 빠르기 때문에 레이 캐스팅을 사용하십시오.
일반적으로 지형에 대한 3D 데이터 구조를 피할 수 있습니다. 대신 하이트 맵을 사용할 수 있습니다 . 이것은 런타임에 매우 저렴하고 효율적으로 복셀 될 수 있습니다. 일반적으로 (내 경험상) 각 열에서 렌더링 해야하는 최소 높이를 추적하고 때로는 시작-정지 각도를 추적하여 후면 열을 컬링 할 수 있습니다.
내가 오랫동안 돌아간 것입니다 : http://sites.google.com/site/williamedwardscoder/spinning-voxels-in-flash
지형에 하이트 맵으로 표현할 수없는 돌출부 나 동굴 또는 기타 지형지 물이 적은 경우, 하이트 맵에 구멍이 생길 수 있으며 런타임 비용이 드는 현지화 된 장소를 채우는 진정한 3D 복셀 객체와 같은 대체 표현이 가능합니다 보증됩니다.
희귀 복셀 표현 은 큰 실제 복셀 세계가있을 때 가치가 있습니다. 존 카맥 (John Carmack) 은 지난 몇 년 동안 그들에게 이야기 해 왔습니다 ...