이전에 IsoSurface를 렌더링하기 위해 행진 큐브 / 사면체를 구현했습니다. 그것은 효과가 있었지만 ( YouTube ), 뷰 거리를 기준으로 가변 레벨의 디테일을 구현하거나 심지어 먼 오래된 청크를 제거하지 않아도 성능이 심각했습니다.
나는 이번에 또 다른 일을하기로 결정했습니다. Build()
호출 될 때 다음과 같이 작동하는 OctreeNode를 작성하여 시작했습니다 .
- 청크가 너무 작아 빌드 할 수 없으면 즉시 반환하십시오.
- 표면이이 덩어리의 볼륨을 통과하는지 확인하십시오.
- 그렇다면 LOD를 올릴 것인지 결정하십시오 (카메라가 가까이 있기 때문에)
- 그렇다면 8 명의 자식을 생성하고 같은 프로세스를 호출하십시오.
- 그렇지 않은 경우 현재 노드의 치수를 사용하여 메쉬를 작성하십시오
일부 유사 코드 :
OctNode Build() {
if(this.ChunkSize < minChunkSize) {
return null;
}
densityRange = densitySource¹.GetDensityRange(this.bounds);
if(densityRange.min < surface < densityRange.max) {
if(loDProvider.DesiredLod(bounds)² > currentLoD) {
for(i 1 to 8) {
if(children[i] == null) {
children[i] = new OctNode(...)
}
children[i] = children[i].Build();
}
} else {
BuildMesh();
}
return this;
}
}
¹ 한 지점에서 밀도를 반환 할뿐만 아니라 밀도 소스는 주어진 부피에 대해 가능한 밀도 범위를 결정할 수 있습니다.
² LoD 제공 업체는 경계 상자를 사용하여 카메라 위치 / 절두체, 사용자 설정 등에 따라 원하는 최대 LoD를 반환합니다.
그래서 ...이 모든 것이 상당히 잘 작동합니다. 간단한 구체를 밀도 소스로 사용하고 모든 노드를 표시합니다.
그리고 나뭇잎 만 :
그러나 몇 가지 문제가 있습니다.
- 초기 바운딩 볼륨을 정의해야합니다 (그리고 클수록 클수록 처리가 더 필요합니다)
- 나무의 뿌리에서 나는 잎이 얼마나 깊을 지 모른다. 그래서 LoD 번호는 최저 품질 (루트)에서 시작하여 덩어리가 작아 질수록 증가한다. LoD는 이제 초기 볼륨을 기준으로하기 때문에 특정 크기 / 품질로 작업을 수행 할 때는 많이 사용하지 않습니다.
몇 가지 옵션을 생각했지만 둘 다 결함이있는 것 같습니다.
- Octrees 컬렉션을 유지하고 거리에 따라 추가 / 제거합니다. 멋지게 메쉬되는 방법을 볼 수 없음 ¹, 특히 임의의 3D 표면을 원할 경우 비어있는 볼륨의 목록이 필요합니다 (빈 볼륨을 반복적으로 다시 계산하지 않기 위해)
- 현재 루트에 상위 노드를 추가 한 다음 원래 노드에 7 개의 형제를 추가하십시오. 이것은 작동하고 주문형이지만 플레이어가 가로 방향으로 이동할 때 현명하게 축소되는 것은 복잡해 보입니다. 또한 LoD 숫자는 덜 의미가 있습니다.
¹ [아래 Q에 대한 설명에서] 현재 트리에서 물리적으로 인접한 2 개의 노드가 서로 다른 LOD에 있으면 메쉬가 생성 될 때 이음새가 없도록 vert를 강제하는 코드가 있습니다. 여러 주변 노드의 밀도를 알고 있으면이 작업을 수행 할 수 있습니다. 2 개의 독립적 인 옥트리가 나란히있는 시나리오에서는이 정보를 쉽게 검색 할 수 없으므로 이음새가 생깁니다.
이것에 접근하는 가장 좋은 방법은 무엇입니까?