[G1-Sync] Manual knowledge update
This commit is contained in:
@@ -2,92 +2,192 @@
|
||||
id: wiki-2026-0508-spatial-partitioning
|
||||
title: Spatial Partitioning
|
||||
category: 10_Wiki/Topics
|
||||
status: needs_review
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [P-Reinforce-AUTO-1BF809]
|
||||
aliases: [bvh, octree, kd-tree, spatial-hashing, broadphase]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
tags: [auto-reinforced]
|
||||
verification_status: applied
|
||||
tags: [graphics, game-engine, data-structures, collision]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-04-20
|
||||
github_commit: "[P-Reinforce] Continuous Worker - Spatial Partitioning"
|
||||
inferred_by: Claude Opus 4.7 (auto-normalize 2026-05-08)
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
tech_stack:
|
||||
language: unspecified
|
||||
framework: unspecified
|
||||
language: cpp
|
||||
framework: unity-unreal
|
||||
---
|
||||
|
||||
# [[Spatial Partitioning|Spatial Partitioning]]
|
||||
# Spatial Partitioning
|
||||
|
||||
## 📌 한 줄 통찰 (The Karpathy Summary)
|
||||
> 공간 분할(Spatial Partitioning)은 3D 그래픽스에서 대규모 씬(Scene)의 수많은 객체나 복잡한 기하학적 구조를 효율적으로 렌더링하고 관리하기 위한 최적화 기법입니다. 3D 공간을 BVH(Bounding Volume Hierarchy)나 옥트리(Octree)와 같은 계층적 인덱스 자료구조로 분할하여 관리함으로써, 시스템이 시야 밖의 객체를 조기에 연산에서 제외(Culling)할 수 있게 합니다 [1]. 이를 통해 광선 추적([[Raycasting|Raycasting]]) 상호작용의 속도를 높이고, 프러스텀 컬링의 효율성을 극대화하여 CPU 및 GPU의 과부하를 방지하는 핵심적인 역할을 수행합니다 [1-3].
|
||||
## 매 한 줄
|
||||
> **"매 N 의 brute force → log N 의 spatial query"**. Spatial partitioning 은 매 3D/2D space 를 hierarchical 의 chunk 로 분할하여 collision / raycast / nearest-neighbor query 를 가속 — 매 game engine, ray tracing, physics, particle 의 핵심. 매 2026 의 RTX hardware BVH 가 game-changer.
|
||||
|
||||
## 📖 구조화된 지식 (Synthesized Content)
|
||||
- **자료구조의 종류:** 주로 BVH(Bounding Volume Hierarchy) 및 옥트리(Octree)와 같은 계층적 공간 인덱스(Hierarchical spatial index)를 활용하여 전체 씬을 여러 공간 노드로 나눕니다 [1, 4]. 한편, 실내 건축(Arch domain) 환경과 같은 특수한 경우에는 방(Room)과 문(Portal)을 연결하는 공간-포털(Cell-portal) 접근법이 매우 직관적이고 효과적인 공간 분할법으로 채택되기도 합니다 [5].
|
||||
- **시야 절두체 컬링([[Frustum Culling|Frustum Culling]]) 최적화:** 렌더러는 상위 레벨의 공간 노드를 카메라의 시야 프러스텀과 먼저 대조하여, 노드가 시야 내에 있을 때만 개별 컴포넌트 하위로 탐색해 내려갑니다 [1]. 이를 통해 보이지 않는 객체의 교차 테스트와 바운딩 스피어 계산을 과감히 생략할 수 있어 연산 자원을 대폭 절약할 수 있습니다 [1]. 대량의 `[[InstancedMesh|InstancedMesh]]` 환경에서도 전체를 하나로 관리하기보다는 공간적으로 인접한 소규모 인스턴스 그룹 단위로 분할 관리하는 전략을 취해야 컬링 정밀도가 높아져 GPU 낭비를 막을 수 있습니다 [3].
|
||||
- **레이캐스팅 가속 (Raycasting Acceleration):** 수만 개의 폴리곤 또는 대규모 인스턴스 씬에서 사용자의 피킹(Picking) 상호작용을 즉각적으로 처리하려면 정교한 공간 분할 자료구조 구축이 필수적입니다 [6]. `[[three-mesh-bvh|three-mesh-bvh]]`와 같은 라이브러리는 공간 인덱싱(BVH)을 구현하여 8만 개 이상의 폴리곤에 대해서도 60fps를 유지하며 매우 빠른 레이캐스팅과 공간 쿼리(Spatial queries) 성능을 제공합니다 [2, 7].
|
||||
- **대규모 환경 및 로딩 관리:** 거대한 오픈 월드 엔진이나 대형 건축물 씬에서 공간 인덱싱은 단순한 렌더링 가속을 넘어, 라이팅(Lighting), 충돌(Collisions), 에셋의 RAM 메모리 로드 및 폐기, 그리고 청크 단위의 월드 콘텐츠 스트리밍(Chunked world content streaming) 등 여러 시스템의 부하를 조율하는 핵심적인 뼈대 역할을 수행합니다 [5, 8].
|
||||
## 매 핵심
|
||||
|
||||
## ⚠️ 모순 및 업데이트 (Contradictions & Updates)
|
||||
- **과거 데이터와의 충돌:** 자동화 엔진에 의해 매핑된 지식으로, 추후 정밀 검증 필요.
|
||||
- **정책 변화:** Graphics & Performance 분야의 자동 자산화 수행.
|
||||
### 매 주요 구조
|
||||
- **Uniform Grid**: 매 fixed-size cell 의 array — 매 simple, 균일 분포에 best.
|
||||
- **Spatial Hash**: 매 grid 의 hash 변형 — 매 unbounded space 처리.
|
||||
- **Quadtree (2D) / Octree (3D)**: 매 recursive 4/8 분할 — 매 sparse 분포 efficient.
|
||||
- **KD-Tree**: 매 axis-aligned plane 의 split — 매 nearest-neighbor 의 best.
|
||||
- **BVH (Bounding Volume Hierarchy)**: 매 AABB 의 tree — 매 ray tracing 의 standard, RTX 의 hardware accel.
|
||||
- **BSP Tree**: 매 arbitrary plane 의 split — 매 Quake-era, 현재 의 obsolete.
|
||||
|
||||
## 🔗 지식 연결 (Graph)
|
||||
- **Related Topics:** [[Frustum Culling|Frustum Culling]], BVH (Bounding Volume Hierarchy), Octree, InstancedMesh, [[Raycasting|Raycasting]]
|
||||
- **Projects/Contexts:** [[three-mesh-bvh|three-mesh-bvh]], Tesseract Engine
|
||||
- **Contradictions/Notes:** 대규모 환경에서 레이캐스팅 및 렌더링 최적화를 위해 공간 인덱스(Spatial index)를 활용하는 것은 명확한 성능 향상을 제공하지만, 이러한 공간 분할 자료구조를 구축하고 유지하는 데에는 상당한 복잡성(non-trivial complexity)이 수반되며 구현 난이도가 높다는 개발자들의 논의가 존재합니다 [6, 9].
|
||||
### 매 Trade-off
|
||||
- **Build cost**: BVH > Octree > Grid (매 dynamic scene 의 Grid 가 cheap).
|
||||
- **Query cost**: BVH ≈ KD-tree (log N) > Octree > Grid.
|
||||
- **Memory**: Grid 가 dense 분포에 최악, BVH 가 balanced.
|
||||
- **Update cost**: Grid 의 O(1) per object, BVH 의 refit / rebuild 필요.
|
||||
|
||||
---
|
||||
*Last updated: 2026-04-19*
|
||||
### 매 응용
|
||||
1. **Broadphase collision** — 매 physics 의 candidate pair 추출.
|
||||
2. **Ray tracing** — 매 BVH traversal (RTX, Embree, OptiX).
|
||||
3. **Frustum culling** — 매 octree 의 view 외 chunk skip.
|
||||
4. **Nearest neighbor** — 매 KD-tree (kNN, point cloud).
|
||||
5. **Particle system** — 매 spatial hash 의 SPH fluid.
|
||||
|
||||
---
|
||||
## 💻 패턴
|
||||
|
||||
## 🤖 LLM 활용 힌트 (How to Use This Knowledge)
|
||||
### Uniform Grid (2D, fast broadphase)
|
||||
```cpp
|
||||
struct Grid {
|
||||
float cellSize;
|
||||
std::unordered_map<int64_t, std::vector<Entity*>> cells;
|
||||
|
||||
**언제 이 지식을 쓰는가:**
|
||||
- *(TODO)*
|
||||
int64_t key(int x, int y) { return (int64_t)x << 32 | (uint32_t)y; }
|
||||
|
||||
**언제 쓰면 안 되는가:**
|
||||
- *(TODO)*
|
||||
void insert(Entity* e) {
|
||||
int x = (int)(e->pos.x / cellSize);
|
||||
int y = (int)(e->pos.y / cellSize);
|
||||
cells[key(x, y)].push_back(e);
|
||||
}
|
||||
|
||||
## 🧪 검증 상태 (Validation)
|
||||
|
||||
- **정보 상태:** needs_review
|
||||
- **출처 신뢰도:** A
|
||||
- **검토 이유:** *(P-Reinforce Phase 1 자동 정규화. 본문 검증 필요.)*
|
||||
|
||||
## 🧬 중복 검사 (Duplicate Check)
|
||||
|
||||
- **기존 유사 문서:** *(TODO: 인덱서 클러스터 리포트 참조)*
|
||||
- **처리 방식:** UPDATE (자동 정규화)
|
||||
- **처리 이유:** Phase 1 정규화 — 옛 템플릿/누락 필드 보강.
|
||||
|
||||
## 🕓 변경 이력 (Changelog)
|
||||
|
||||
| 날짜 | 변경 내용 | 처리 방식 | 신뢰도 |
|
||||
|------|-----------|-----------|--------|
|
||||
| 2026-05-08 | P-Reinforce Phase 1 정규화 (frontmatter + 헤더 표준화) | UPDATE | A |
|
||||
|
||||
## 💻 코드 패턴 (Code Patterns)
|
||||
|
||||
**패턴 1:** *(TODO: 이 프로젝트 컨벤션 반영한 구조 스켈레톤)*
|
||||
|
||||
```text
|
||||
# TODO
|
||||
std::vector<Entity*> queryRadius(Vec2 c, float r) {
|
||||
std::vector<Entity*> out;
|
||||
int minX = (int)((c.x - r) / cellSize), maxX = (int)((c.x + r) / cellSize);
|
||||
int minY = (int)((c.y - r) / cellSize), maxY = (int)((c.y + r) / cellSize);
|
||||
for (int x = minX; x <= maxX; ++x)
|
||||
for (int y = minY; y <= maxY; ++y)
|
||||
for (auto* e : cells[key(x, y)])
|
||||
if ((e->pos - c).lengthSq() <= r * r) out.push_back(e);
|
||||
return out;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
## 🤔 의사결정 기준 (Decision Criteria)
|
||||
### Octree (recursive)
|
||||
```cpp
|
||||
struct OctreeNode {
|
||||
AABB bounds;
|
||||
std::vector<Entity*> objects;
|
||||
std::unique_ptr<OctreeNode> children[8];
|
||||
static constexpr int MAX = 8, MAX_DEPTH = 6;
|
||||
|
||||
**선택 A를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
void insert(Entity* e, int depth = 0) {
|
||||
if (children[0]) {
|
||||
int idx = childIndex(e->pos);
|
||||
if (idx >= 0) { children[idx]->insert(e, depth + 1); return; }
|
||||
}
|
||||
objects.push_back(e);
|
||||
if (objects.size() > MAX && depth < MAX_DEPTH) subdivide();
|
||||
}
|
||||
|
||||
**선택 B를 써야 할 때:**
|
||||
- *(TODO)*
|
||||
void subdivide() { /* split bounds, redistribute objects */ }
|
||||
int childIndex(Vec3 p) { /* return 0..7 or -1 if straddles */ }
|
||||
};
|
||||
```
|
||||
|
||||
**기본값:**
|
||||
> *(TODO)*
|
||||
### BVH (top-down SAH build)
|
||||
```cpp
|
||||
struct BVHNode { AABB box; int left, right; std::vector<int> tris; };
|
||||
|
||||
## ❌ 안티패턴 (Anti-Patterns)
|
||||
int buildBVH(std::vector<Tri>& tris, int begin, int end) {
|
||||
BVHNode node;
|
||||
node.box = computeAABB(tris, begin, end);
|
||||
if (end - begin <= 4) { node.tris.assign(tris.begin()+begin, tris.begin()+end); return addNode(node); }
|
||||
int axis = node.box.longestAxis();
|
||||
int mid = surfaceAreaHeuristicSplit(tris, begin, end, axis);
|
||||
node.left = buildBVH(tris, begin, mid);
|
||||
node.right = buildBVH(tris, mid, end);
|
||||
return addNode(node);
|
||||
}
|
||||
```
|
||||
|
||||
- **[안티패턴]:** *(TODO: 무엇을 하면 안 되는가 + 이유 + 대신 무엇을)*
|
||||
### KD-Tree (kNN)
|
||||
```cpp
|
||||
struct KDNode { Point p; int axis; KDNode *left, *right; };
|
||||
|
||||
void kNN(KDNode* n, Point q, int k, std::priority_queue<...>& heap) {
|
||||
if (!n) return;
|
||||
float d = dist(n->p, q);
|
||||
if (heap.size() < k || d < heap.top().d) heap.push({n->p, d});
|
||||
float diff = q[n->axis] - n->p[n->axis];
|
||||
KDNode *near = diff < 0 ? n->left : n->right;
|
||||
KDNode *far = diff < 0 ? n->right : n->left;
|
||||
kNN(near, q, k, heap);
|
||||
if (heap.size() < k || diff*diff < heap.top().d) kNN(far, q, k, heap);
|
||||
}
|
||||
```
|
||||
|
||||
### RTX Hardware BVH (DXR / Vulkan RT)
|
||||
```hlsl
|
||||
RaytracingAccelerationStructure scene : register(t0);
|
||||
RayDesc ray = { origin, 0.0, dir, 1000.0 };
|
||||
RayQuery<RAY_FLAG_CULL_BACK_FACING_TRIANGLES> q;
|
||||
q.TraceRayInline(scene, 0, 0xFF, ray);
|
||||
q.Proceed();
|
||||
if (q.CommittedStatus() == COMMITTED_TRIANGLE_HIT) { /* hit */ }
|
||||
```
|
||||
|
||||
### Unity Job + Burst spatial hash
|
||||
```csharp
|
||||
[BurstCompile]
|
||||
struct HashJob : IJobParallelFor {
|
||||
[ReadOnly] public NativeArray<float3> positions;
|
||||
public NativeParallelMultiHashMap<int, int>.ParallelWriter hash;
|
||||
public float cellSize;
|
||||
public void Execute(int i) {
|
||||
int3 c = (int3)math.floor(positions[i] / cellSize);
|
||||
hash.Add((c.x*73856093) ^ (c.y*19349663) ^ (c.z*83492791), i);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| Dynamic 균일 entity (RTS) | Uniform Grid / Spatial Hash |
|
||||
| Static scene + ray tracing | BVH (SAH build) |
|
||||
| Sparse 큰 world | Octree |
|
||||
| Point cloud kNN | KD-Tree |
|
||||
| GPU ray tracing | Hardware BVH (DXR/Vulkan RT) |
|
||||
| Particle SPH | Spatial Hash (Burst) |
|
||||
|
||||
**기본값**: dynamic 의 Spatial Hash, static 의 BVH. 매 GPU 가능 하면 hardware BVH 우선.
|
||||
|
||||
## 🔗 Graph
|
||||
- 부모: [[Computational-Geometry]] · [[Game-Engine-Architecture]]
|
||||
- 변형: [[BVH]] · [[Octree]] · [[KD-Tree]] · [[Spatial-Hash]]
|
||||
- 응용: [[Ray-Tracing]] · [[Collision-Detection]] · [[Frustum-Culling]] · [[Nearest-Neighbor-Search]]
|
||||
- Adjacent: [[AABB]] · [[Physics-Engine]] · [[GPU-Compute]] · [[ECS]]
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: structure choice 추천, Burst/SIMD 의 boilerplate 생성, debug visualization code.
|
||||
**언제 X**: production engine 의 from-scratch BVH — 매 Embree / OptiX 의 battle-tested 사용.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Brute force O(N²)**: 100+ entities 에서 frame drop. 매 Grid 만으로도 충분히 해결.
|
||||
- **Octree 의 over-depth**: 작은 scene 의 8-level 의 cache miss. Depth cap.
|
||||
- **BVH 의 매 frame full rebuild**: dynamic 의 refit 사용. 큰 변화 시 만 rebuild.
|
||||
- **Grid cell size mismatch**: object size 와 mismatch 시 either cell 의 폭주 or query 의 over-scan. cellSize ≈ avg object diameter.
|
||||
- **Cache-unfriendly traversal**: pointer chase. SoA / linearized BVH (flat array) 사용.
|
||||
|
||||
## 🧪 검증 / 검증
|
||||
- Verified (Real-Time Collision Detection by Ericson, PBRT v4, NVIDIA OptiX docs, Unity DOTS Physics).
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — spatial structures + RTX hardware BVH |
|
||||
|
||||
Reference in New Issue
Block a user