설명
새들이 서로 주변만 보고 움직일 때 무리가 어떻게 만들어지는지 보는 시뮬레이션입니다. 찌르레기 군무의 특징 몇 가지를 옵션으로 넣었습니다.
이 시뮬레이션은 무엇을 보여 주나요
화면의 삼각형 하나가 새 한 마리입니다. 각 새는 자기 주변의 새만 보고 속도와 방향을 스스로 정합니다. 무리 전체를 조종하는 규칙은 없는데도, 새들이 모여서 같은 방향으로 움직이는 무리가 생깁니다. 이런 방식을 보이드(boids) 모델이라고 하며, 1986년 Craig Reynolds가 만들었습니다.
이 페이지는 찌르레기 무리(군무)를 흉내 내기 위해, 실제 관찰 연구에서 알려진 특징 몇 가지를 옵션으로 넣었습니다. 실제 새의 움직임을 정확히 재현하는 모델은 아니고, 원리를 눈으로 확인하기 위해 단순하게 만든 모델입니다.
위쪽의 2D / 3D 버튼으로 평면과 3차원 화면을 바꿔 볼 수 있습니다. 3D 화면은 드래그로 회전하고, 휠이나 두 손가락 벌리기로 확대·축소합니다.
Basic은 기본값으로 실행하는 화면이고, Expert는 변수 값을 직접 바꾸는 화면입니다. Expert에서 바꾼 값은 Basic으로 돌아오면 기본값으로 되돌아갑니다. 이웃 방식, 정렬 방식, 포식자 같은 선택 항목과 개체 수는 Basic에서도 바꿀 수 있습니다.
새 한 마리가 따르는 세 가지 규칙
- 분리: 너무 가까운 이웃에게서 멀어집니다. 서로 부딪히지 않게 하는 규칙입니다.
- 정렬: 이웃이 향하는 방향에 자기 방향을 맞춥니다.
- 응집: 이웃들이 모여 있는 쪽으로 다가갑니다.
세 규칙은 각각 가중치라는 숫자로 세기를 조절합니다. 새는 세 규칙이 내는 힘을 더한 만큼 속도와 방향을 바꿉니다. 가중치를 올리면 그 규칙의 영향이 커집니다.
가중치를 크게 한다고 무리가 더 잘 만들어지는 것은 아닙니다. 규칙끼리 서로 반대쪽으로 힘을 주기 때문에, 한 규칙만 지나치게 키우면 무리가 흩어지거나 뭉쳐서 움직임이 이상해질 수 있습니다.
이웃을 정하는 두 가지 방식
새가 "이웃"으로 보는 대상을 정하는 방식이 두 가지 있습니다.
- 보이드 방식: 정해진 거리(인지 반경) 안에 있는 새를 모두 이웃으로 봅니다. 새가 빽빽한 곳에서는 이웃이 수십~수백 마리가 될 수 있고, 이웃이 많을수록 계산이 오래 걸립니다.
- 가장 가까운 N마리 (기본): 거리와 관계없이 가장 가까운 N마리(기본 7)만 이웃으로 봅니다. 찌르레기 무리를 관찰한 연구(Ballerini 등, 2008)에서 새 한 마리가 거리와 관계없이 가장 가까운 6~7마리와 상호작용한다고 보고되어 이 방식을 넣었습니다. 새가 빽빽하든 드물든 이웃 수가 일정합니다.
화면 아래쪽의 "이웃" 값으로 실제 이웃이 몇 마리인지 볼 수 있습니다. N을 너무 작게(예: 1) 하면 정렬이 잘 되지 않는 경우가 있습니다.
정렬 방식: 관성 모델과 기본
- 관성 모델 (기본): 새가 방향을 바꾸는 데도 관성이 있습니다. 이웃과 방향이 다르면 회전하려는 힘이 생기고, 이 힘으로 방향이 서서히 바뀝니다. 그래서 이웃을 곧바로 따라가지 않고 조금 늦게 바뀌며, 지나쳤다가 돌아오는 흔들림이 생기기도 합니다. 찌르레기 무리에서 방향 변화가 무리 속으로 전달되는 현상을 설명하려고 제안된 관성 스핀 모델(Cavagna 등)을 단순하게 구현한 것이며, 실제 연구 수치에 맞춘 것은 아닙니다.
- 기본: 이웃의 평균 속도를 향해 곧바로 조정합니다. 관성이 없어서 방향이 더 빨리 맞춰집니다.
관성 모델에서는 관성 χ와 감쇠 η를 조절할 수 있습니다. χ를 올리면 방향이 더 늦게 바뀝니다. η를 올리면 흔들림이 빨리 줄고, 내리면 오래 흔들립니다.
포식자
"포식자"를 켜면 주황색 포식자가 나타납니다.
- 포식자는 가장 가까운 새를 골라, 그 새가 앞으로 있을 위치를 향해 쫓아갑니다. 속도는 새의 최대 속도의 1.3배(기본)이지만 한 번에 꺾을 수 있는 각도가 제한되어 있어서 급하게 방향을 바꾸지는 못합니다.
- 포식자는 잡을 때까지 쫓아가고 물러서지 않습니다. 목표 새에게 10 이내로 다가가면 그 새를 잡은 것으로 보고 무리에서 뺍니다. 그러면 바로 다음으로 가까운 새를 쫓습니다. 30초 동안 잡지 못하면 가장 가까운 새로 목표를 바꿉니다.
- 화면 아래의 "잡힘"은 잡힌 새의 수, "남음"은 남은 새의 수입니다. 새가 20마리 남으면 더 잡지 않습니다. 초기화를 누르면 새가 다시 채워집니다.
- 포식자 감지 거리 안으로 들어온 새는 포식자에게서 멀어지려 합니다. 가까울수록 더 세게 도망치고, 이때는 최대 속도의 1.3배까지 낼 수 있습니다.
- 감지 거리 안의 새는 세 규칙의 가중치도 바뀝니다. 기본값은 분리 ×1.5, 정렬 ×1.5, 응집 ×0.5입니다. 서로 더 떨어지고 방향은 더 잘 맞추면서 뭉치는 힘은 줄어서, 쫓길 때 무리가 퍼지면서 함께 도망치는 모습이 됩니다. Expert에서 배율을 바꿀 수 있습니다.
- 이 배율은 제가 정한 값입니다. 실제 무리가 공격받을 때는 퍼지는 경우와 뭉치는 경우가 모두 관찰됩니다(Storms 등, 2019). 이 시뮬레이션에서 분리 ×0.6, 정렬 ×1.5, 응집 ×2처럼 뭉치게 하면 포식자가 훨씬 많이 잡았습니다(500마리, 240초 기준 분당 2D 6.6마리 → 11.8마리, 3D 7.3마리 → 21.0마리). 기본 배율(퍼짐)은 배율을 쓰지 않을 때와 잡히는 수가 거의 같았습니다(2D 6.3마리, 3D 7.6마리). 이 포식자는 감지 거리 안의 가장 가까운 새를 잡을 뿐이어서, 뭉친 무리가 포식자를 혼란시키는 효과는 들어 있지 않습니다.
- 포식자를 본 새가 이웃에게 따로 알리지는 않습니다. 도망치는 반응은 정렬·응집 규칙을 통해서만 주변 새에게 퍼집니다. 다만 감지 거리 안의 새에게만 위 배율이 적용됩니다.
화면 표시를 읽는 법
- 빨간 삼각형(크게): 선택 개체입니다. 0번 새 한 마리를 고정해서 표시합니다.
- 연한 빨간 삼각형: 선택 개체와 가장 가까운 7마리입니다. 이웃 방식과 관계없이 항상 7마리를 표시합니다. "가장 가까운 N마리" 방식에서 N이 7이면 실제로 영향을 주는 이웃과 같습니다.
- 정렬도(0~1): 모든 새의 진행 방향을 평균낸 값입니다. 1에 가까우면 거의 모두 같은 방향으로 움직이고, 0에 가까우면 방향이 제각각입니다.
- 이웃: 새 한 마리가 이웃으로 보는 새의 평균 수입니다.
- 잡힘 / 남음: 포식자에게 잡힌 새의 수와 남은 새의 수입니다. 초기화하면 처음 상태로 돌아갑니다.
- fps: 화면이 초당 몇 번 갱신되는지입니다. 낮을수록 화면이 끊깁니다. 새를 많이 늘렸을 때 참고하세요.
- 방향 돌리기 (↶ 왼쪽 / 오른쪽 ↷): 선택 개체 근처의 새들의 방향을 강제로 120도 돌립니다. 방향 변화가 무리로 퍼지는 모습을 볼 때 씁니다. 왼쪽·오른쪽은 새가 향한 방향을 기준으로 하며, 3D에서는 위에서 내려다본 기준입니다. 방향 변화는 돌린 쪽으로 퍼지므로 두 버튼을 번갈아 눌러 비교해 보세요.
- 노란 삼각형: 자발적 전환 중인 새입니다(옵션을 켰을 때). 전환이 시작된 가장자리에서 무리 안으로 퍼지는 모습을 볼 수 있습니다.
- 화면 가장자리: 새가 밖으로 나가지 않도록, 2D는 화면 가장자리에서, 3D는 타원체 모양의 구역 가장자리에서 안쪽으로 방향을 틉니다.
변수 설명
해 볼 만한 실험
- 정렬 가중치를 0으로 내려 보세요. 새들이 방향을 맞추지 않아 정렬도가 크게 낮아지고 무리가 넓게 퍼집니다.
- 분리 가중치를 바꿔 보세요. 낮추면 새들이 겹치고, 높이면 새 사이 간격이 넓어집니다.
- 응집 가중치를 0으로 내려 보세요. 무리 크기와 정렬도가 어떻게 변하는지 봅니다. 결과는 2D와 3D, 이웃 방식에 따라 다르게 나타납니다.
- 이웃 방식을 "가장 가까운 N마리"로 바꾸고 N을 1, 7, 20으로 바꿔 보세요.
- 포식자를 켜고 쫓길 때의 분리·정렬·응집 배율을 바꿔 보세요. 응집 배율을 키우고 분리 배율을 줄이면 무리가 뭉치고, 반대로 하면 퍼집니다. "잡힘" 수가 어떻게 달라지는지 봅니다.
- "방향 돌리기"의 왼쪽·오른쪽을 관성 모델과 기본 방식에서 각각 눌러 보세요. 주변 새들의 반응이 나타나는 속도와 방식을 비교해 봅니다.
수식으로 보기 (선택)
수식이 필요 없는 분은 건너뛰셔도 됩니다.
새 한 마리의 속도 변화 = w_sep × 분리 + w_ali × 정렬 + w_coh × 응집 (여기에 포식자 회피와 경계 힘이 더해집니다). 세 힘은 모두 "원하는 속도 − 현재 속도"를 최대 힘(0.1) 이하로 자른 값입니다. 분리는 분리 거리 안의 이웃에서 멀어지는 방향, 정렬은 이웃 평균 속도 방향, 응집은 이웃 평균 위치 방향을 원하는 방향으로 삼습니다.
관성 모델에서는 정렬 항 대신 회전 토크를 씁니다. 토크 τ는 자기 방향과 이웃 방향의 차이(2D에서는 sin값의 평균, 3D에서는 외적의 평균)이고, 회전 상태 s는 s ← s + J·τ − (η/χ)·s로 갱신됩니다(J = 0.06 × w_ali). 각속도는 ω = s/χ이며 프레임당 0.35 rad을 넘지 않게 제한하고, 속도 방향을 ω만큼 회전시킵니다. 이 방식은 정렬 항이 속도를 최대 속도 쪽으로 밀어주지 않으므로, 속도를 최대 속도 쪽으로 서서히 되돌리는 보정을 함께 씁니다.
정렬도 = 새들의 진행 방향(단위벡터)을 모두 더한 벡터의 크기 ÷ 새의 수.
실제 무리와 비교한 결과 (Cavagna 그룹 논문)
- 가장자리 새가 더 자주 벗어남: 실제 무리에서는 옆쪽 가장자리의 새일수록 무리 평균 방향에서 자주 벗어납니다(Attanasi 등, 2015). 이 시뮬레이션에서도 정렬도가 0.85 이상인 때의 측정값이 2D·3D 모두 바깥 10%는 약 0.65~0.81, 안쪽 50%는 약 0.40~0.44로 나왔습니다(500마리, 이웃·정렬 방식 5가지 조합). 이 결과를 위한 규칙을 따로 넣지 않았는데도 나타났습니다.
- 무리 모양: 실제 무리는 곧게 날 때 가장 긴 축이 이동 방향과 수직에 가깝습니다. 이동 방향과 가장 긴 축의 |cos|가 대개 0.5 미만입니다. 이 시뮬레이션에서 정렬도가 0.8 이상인 구간(3D, 500마리)을 잰 값은 "가장 가까운 N마리 + 관성 모델"에서 N=7일 때 0.44, N=12일 때 0.20이었고, 보이드 방식은 0.52, 기본 정렬은 0.57이었습니다. 표본이 30여 개 구간이라 대략적인 값입니다.
- 속도 변화: 실제 무리의 개체 속도 변화는 평균 속도 대비 분산 약 0.005입니다(Bialek 등, 2014). 이 시뮬레이션의 기본값은 약 0.002로 같은 자릿수입니다.
- 이웃 상호작용만으로는 재현되지 않은 것: 가장자리의 소수가 시작한 방향 전환이 무리 전체로 퍼지는 과정입니다. 소수의 새만 돌리면 무리 평균 방향은 그 새들의 비율만큼만 바뀝니다(500마리 중 10마리를 60도 돌리면 약 1도). 그래서 "자발적 전환" 옵션은 전환 신호가 퍼지는 속도와 새들의 회전 속도를 미리 정해 두는 방식으로 넣었습니다.
자발적 전환 (기본으로 켜져 있음, 실험)
실제 찌르레기 무리는 포식자가 없어도 방향을 자주 바꿉니다. 이 옵션은 그 변화를 단순하게 흉내 냅니다. 논문의 공식이 아니라 관찰을 옮긴 규칙입니다.
- 무작위 시각에, 무리 진행 방향의 옆쪽 가장자리에 있는 서로 가까운 새 10마리 안팎이 안쪽으로 돌기 시작합니다(Attanasi 등, 2015).
- 다른 새는 시작 지점에서의 거리에 비례해 늦게, 같은 방향으로 돌기 시작합니다. 전환 신호가 퍼지는 속도는 새의 최대 속도의 2.5배로 정했습니다. 실제 무리에서 방향 변화 정보가 일정한 속도로 퍼진다는 관찰(Attanasi 등, 2014)을 옮긴 것으로, 값은 제가 정했습니다.
- 모든 새가 같은 회전 속도로 정해진 각도만큼만 돌기 때문에 새마다 같은 반지름의 경로를 따라갑니다. 실제 무리도 같은 반지름의 경로로 돕니다.
전환이 시작되는 시각과 각각의 새가 돌기 시작하는 시각은 미리 정해 둔 것이며, 새들 사이의 상호작용에서 나온 결과가 아닙니다. 전환 중에도 분리·정렬·응집 규칙은 그대로 작용합니다.
끄려면 옵션 줄의 "자발적 전환"을 해제하세요. Expert에서 평균 간격과 각도를 바꿀 수 있습니다. 3D 500마리 시험(보이드 방식)에서 평균 간격 6초, 각도 90도로 하면 무리 중심이 같은 경로를 왕복하는 규칙성이 줄었습니다. 반복 정도가 0.99에서 0.52로 낮아졌고, 정렬도가 0.6 미만인 시간은 18%에서 5%로 줄었습니다.
녹화
- 표시줄의 ● 녹화를 누르면 시뮬레이션 화면(캔버스)을 녹화하고, 다시 누르면 정지합니다. 옆의 패널이나 표시줄은 영상에 들어가지 않습니다. 정지하면 "녹화 저장" 버튼이 나타납니다.
- 자발적 전환 포함(기본으로 켜짐): 녹화하는 동안 자발적 전환이 반드시 일어나게 합니다. 자발적 전환이 꺼져 있어도 녹화하는 동안은 켜고, 녹화를 시작하고 3초 뒤에 첫 전환을 시작합니다. 녹화가 끝나면 원래 설정으로 돌아갑니다. 끄면 지금 설정 그대로 녹화합니다.
- 자동 정지: 정한 시간이 지나면 저절로 정지합니다.
- 파일 형식은 브라우저가 지원하는 것으로 정해집니다(mp4 또는 webm). 녹화 중에 창 크기를 바꾸면 영상 크기가 바뀔 수 있습니다.
- "화면 녹화용"으로 쓰던 설정 숨기기와 함께 쓰면 화면만 크게 녹화할 수 있습니다.
일시정지와 다시 보기
- 새가 움직이는 동안 프로그램은 최근 10초(초당 30프레임)를 계속 저장해 둡니다.
- 일시정지를 누르면 화면 아래에 다시 보기 표시줄이 나타납니다. 일시정지한 뒤의 화면은 계산하지 않으므로, 저장된 것은 멈추기 직전 10초입니다.
- ▶를 누르면 저장된 10초를 처음부터 재생하고, 슬라이더로 원하는 시점으로 옮길 수 있습니다. 속도는 0.1배·0.25배(기본)·0.5배·1배 중에서 고릅니다. 저장된 프레임 사이를 보간해서 느리게 봐도 부드럽게 보입니다.
- 3D에서는 다시 보는 중에도 드래그로 회전하고 확대·축소할 수 있습니다. 아래 표시줄의 정렬도·잡힘·남음도 그 시점의 값으로 바뀝니다.
- 슬라이더의 맨 끝이 일시정지한 순간입니다. "재생"(일시정지 버튼)을 누르면 그 순간부터 이어서 계산합니다. 다시 본 위치에서 이어지지는 않습니다.
- 영상으로 만들기: 선택한 속도로 처음부터 한 번 재생하면서 녹화하고, 끝나면 "영상 저장"이 나타납니다. 0.25배로 만들면 10초 구간이 40초짜리 영상이 됩니다.
- 저장은 2D와 3D에 따로 됩니다. 초기화하거나 개체 수를 바꾸면 지워집니다. 저장에는 메모리를 씁니다(3D 기준 500마리 약 4MB, 2000마리 약 15MB, 10000마리 약 75MB. 2D는 그보다 적습니다).
알아둘 점과 한계
- 실제 새의 비행 역학(회전할 때 몸이 기울어지는 것, 속도 변화), 시야 제한, 바람은 넣지 않았습니다.
- 3D에서는 무리가 처음에 대체로 같은 방향으로 나는 상태로 시작합니다. 방향이 제각각인 상태에서 시작하면 무리가 질서를 찾는 데 오래 걸리는 경우가 많았습니다(3D 500마리, 무작위 시작 3번 중 2번은 40초 뒤에도 정렬도가 0.5 아래).
- 기본값은 무리가 안정적으로 보이도록 정한 값이며, 실제 찌르레기 측정값과 맞춰서 검증한 것이 아닙니다.
- 새는 최대 10000마리까지 늘릴 수 있지만, 많을수록 계산이 오래 걸려 화면이 느려집니다. 특히 "보이드 방식"에서 반경이 크고 새가 많으면 이웃이 수백 마리가 되어 크게 느려집니다. 새를 많이 늘릴 때는 "가장 가까운 N마리" 방식이나 작은 반경을 권합니다. 화면 아래의 fps 값이 낮아지면(대략 20 이하) 개체 수를 줄이세요.
- 2D는 가로 960 × 세로 540 크기의 고정된 공간에서 계산하고 화면 크기에 맞춰 확대·축소해 보여 줍니다. 3D는 타원체(반지름 520 × 260 × 420) 구역 안에서 움직이며, 2D와 3D는 각각 따로 계산합니다.