Neighbor Grid Simulation
공간 해싱(Spatial Hashing) 기반의 Neighbor Grid 3D로 파티클 간 상호작용을 구현합니다.
Neighbor Grid 3D 개념
공간 해싱으로 효율적인 이웃 탐색
Neighbor Grid 3D는 3D 공간을 균일한 격자(Grid)로 분할하고, 각 파티클을 해당 셀에 등록하는 공간 해싱 구조입니다. 이를 통해 특정 파티클의 근접 이웃을 O(1)에 가까운 시간으로 검색할 수 있습니다.
// 전체 공간을 격자로 분할
// 각 파티클은 자신의 위치에 해당하는 셀에 등록
// 이웃 검색 시 인접 셀(3x3x3 = 27개)만 확인
공간 분할 예시 (2D 단순화):
+-----+-----+-----+-----+
| | P1 | | |
+-----+-----+-----+-----+
| | P0 | P2 | | P0의 이웃: P1, P2, P3
+-----+-----+-----+-----+ (인접 셀에 있는 파티클만 검색)
| | P3 | | |
+-----+-----+-----+-----+
| | | | |
+-----+-----+-----+-----+
셀 크기(Cell Size) 가 중요:
작은 셀 → 정밀한 검색, 높은 메모리/연산 비용
큰 셀 → 빠른 검색, 불필요한 파티클도 포함
N개 파티클 간 모든 쌍을 비교하면 O(N^2)의 비용이 듭니다. 10만 파티클이면 100억 번의 비교가 필요합니다. Neighbor Grid를 사용하면 각 파티클당 인접 셀의 파티클만 확인하므로, 평균적으로 O(N x K) (K = 평균 이웃 수)로 줄어듭니다.
Neighbor Grid 설정 절차
Data Interface 추가부터 Simulation Stage까지
// 전제 조건: GPU Compute Sim 모드 필수
Step 1: Neighbor Grid 3D Data Interface 추가
Emitter Spawn → Set (NeighborGrid3D)
{
Num Cells X/Y/Z: 32 // 각 축의 셀 수
World BBox Size: 1000.0 // 그리드 전체 크기 (cm)
Max Neighbors Per Cell: 16 // 셀당 최대 파티클 수
}
Step 2: Simulation Stage 1 - 파티클을 그리드에 등록
Iteration Source: Particles
└ Neighbor Grid 3D - Fill Grid
Grid: NeighborGrid3D
Position: Particles.Position
Step 3: Simulation Stage 2 - 이웃 검색 및 힘 계산
Iteration Source: Particles
└ Custom Scratch Pad Module
// 이웃 파티클과의 상호작용 로직
Step 4: Particle Update - 결과 반영
└ Solve Forces and Velocity
주요 Neighbor Grid 함수
| 함수 | 용도 |
|---|---|
Num Cells.Set |
그리드의 셀 수 설정 (초기화) |
SetParticleNeighborCount |
특정 셀에 이웃 수 기록 |
GetParticleNeighborCount |
특정 셀의 이웃 수 조회 |
GetParticleNeighbor |
특정 셀의 N번째 이웃 파티클 인덱스 반환 |
NeighborGridIndexToLinear |
3D 셀 인덱스를 1D 인덱스로 변환 |
파티클 간 충돌/반발 구현
Neighbor Grid를 활용한 인터랙션
// Simulation Stage 2의 Scratch Pad 모듈 내부
// 입력: InPosition, InGrid (NeighborGrid3D), InRepelForce, InMinDistance
// 출력: OutForce (Vector3)
float3 TotalForce = float3(0, 0, 0);
int CellX, CellY, CellZ;
// 현재 파티클의 셀 좌표 계산
InGrid.WorldToUnit(InPosition, CellX, CellY, CellZ);
// 인접 27개 셀 순회 (-1, 0, +1)
for (int dx = -1; dx <= 1; dx++)
for (int dy = -1; dy <= 1; dy++)
for (int dz = -1; dz <= 1; dz++)
{
int NX = CellX + dx, NY = CellY + dy, NZ = CellZ + dz;
int NeighborCount;
InGrid.GetParticleNeighborCount(NX, NY, NZ, NeighborCount);
for (int i = 0; i < NeighborCount; i++)
{
int NeighborIdx;
InGrid.GetParticleNeighbor(NX, NY, NZ, i, NeighborIdx);
float3 NeighborPos;
// Particle Attribute Reader로 이웃 위치 읽기
InputDataFloat(NeighborIdx, 0, NeighborPos.x);
InputDataFloat(NeighborIdx, 1, NeighborPos.y);
InputDataFloat(NeighborIdx, 2, NeighborPos.z);
float3 Dir = InPosition - NeighborPos;
float Dist = length(Dir);
if (Dist > 0.001 && Dist < InMinDistance)
{
float Strength = 1.0 - Dist / InMinDistance;
TotalForce += normalize(Dir) * Strength * InRepelForce;
}
}
}
OutForce = TotalForce;
World BBox Size / Num Cells가 셀 크기를 결정합니다. 셀 크기는 파티클 간 최대 상호작용 거리(InMinDistance)와 같거나 약간 크게 설정해야 합니다. 너무 작으면 이웃을 놓치고, 너무 크면 불필요한 검색이 늘어납니다.
실전 활용 사례
Boids, SPH, 군중 시뮬레이션
Boids (군집 행동)
새떼, 물고기 떼 등의 군집 행동은 Neighbor Grid의 대표적 활용 사례입니다. 3가지 규칙으로 구현합니다.
| 규칙 | 설명 | 구현 |
|---|---|---|
| Separation | 너무 가까운 이웃으로부터 멀어지기 | 거리 기반 반발력 |
| Alignment | 이웃의 평균 방향으로 정렬 | 이웃 Velocity 평균 계산 |
| Cohesion | 이웃의 중심으로 모이기 | 이웃 Position 평균 방향으로 힘 |
Neighbor Grid 시뮬레이션에서 Max Neighbors Per Cell은 셀당 저장할 수 있는 최대 파티클 수입니다. 이 값을 초과하면 일부 파티클이 무시됩니다. 너무 높게 설정하면 메모리와 검색 비용이 증가합니다. 일반적으로 8~32가 적절합니다.
핵심 요약
- Neighbor Grid 3D는 공간 해싱으로 파티클의 이웃을 효율적으로 검색하는 Data Interface입니다.
- 구현 절차: Grid 초기화 → Sim Stage 1(Grid 채우기) → Sim Stage 2(이웃 검색) → 결과 반영
- 셀 크기는 파티클 간 최대 상호작용 거리와 같거나 크게 설정해야 합니다.
- Max Neighbors Per Cell은 8~32가 적절하며, 초과 시 파티클이 무시됩니다.
- Boids(군집), SPH(유체), 반발/충돌 등 파티클 간 상호작용의 핵심 기술입니다.
- GPU Compute Sim에서만 사용 가능하며, Simulation Stage와 함께 동작합니다.
도전 과제
배운 내용을 직접 실습해보세요
Neighbor Grid3D Data Interface를 추가하고, Particle Spawn에서 그리드에 파티클을 등록, Particle Update에서 이웃 파티클을 검색하는 기본 구조를 만드세요. Grid Cell Size와 Max Neighbors를 실험하세요.
Neighbor Grid로 주변 파티클을 검색한 뒤, 거리에 따른 인력(가까우면 척력, 멀면 인력)을 적용하여 파티클이 균일한 간격을 유지하며 뭉치는 시뮬레이션을 만드세요.
Boids 알고리즘(Separation, Alignment, Cohesion)을 Neighbor Grid를 사용하여 구현하세요. 수천 개의 파티클이 새떼처럼 군집 행동을 하는 GPU 기반 시뮬레이션을 완성하세요.