* 정의
점곱(dot product)이라고도 부르는 내적(inner product)은 스칼라값을 내는 벡터 곱셈의 일종이다.
결과가 스칼라기 때문에 스칼라 곱(scalar product)이라고 부르기도 한다.
- 기본 공식
다음 두 벡터가 영벡터가 아닐 때 다음과 같이 정의된다. (위치를 내적하는 것은 의미가 없고, 영벡터와 내적하면 모두 0이 나오기 때문에 각도를 사용할 수 없다.)
U = (ux, uy, uz), V = (vx, vy, vz) 일 때, 내적은 다음과 같이 정의된다.
U · V = ux * vx + uy * vy + uz * vz
- 사이 각도와 관련된 공식
기하학적 의미를 확인하기 위해서 제1 코사인법칙 > 제2 코사인법칙 > 내적의 공식을 통해서 새로운 식을 유도할 수 있다. 유도된 식은 다음과 같다.
U · V = ||U|| ||V|| cosθ
- 사이 각도
여기서 두 벡터 사이의 각도 θ는 두 벡터 U와 V로 만들어지는 두 각도 중 더 작은 각도를 의미한다. (0 <= θ <= π)
사이 각도 θ에 대해서 식을 써보면 다음과 같다.
θ = cos-1( U · V / ||U|| ||V||)
여기서 ||U||와 ||V||가 0이 아닌 양수이기 때문에 다음과 같은 속성을 가지고 있다.

- U · V = 0 이면 U⊥V이다 (θ = π/2)
- U · V > 0 이면 (0 <= θ < π/2)을 만족한다.
- U · V < 0 이면 (π/2 < θ <= π)을 만족한다.
- 두 벡터가 평행할 때 절댓값이 가장 크다.
내적의 절댓값을 비교하면 두 벡터가 얼마나 평행한 지 확인할 수 있다.
활용 예시를 하나 들어보면 한 축을 의미하는 벡터에 내적을 했을 때 양수면 해당 축의 양의 영역에 있는 것이고, 음수면 해당 축의 음의 영역이 있다고 판단할 수 있다.
간단한 예제를 확인해보면
U = (2, 4, 5), V = (-1, -5, 3)이라고 할 때, U와 V사이의 각도를 구해보자.
θ = cos-1((2 * -1 + 4 * -5 + 5 * 3) / √(2² + 4² + 5²) * √(-1² + -5² + 3²)) = cos-1(-7 / √45 * √35)
* 사용 이유
- 게임에서 사용하는 방식
게임에서는 두 방향 벡터를 가지고 그 사이의 각도를 구하기 위해서 사용된다. 위에서 구한 식을 사용한다.
θ = cos-1( U · V / ||U|| ||V||)
이를 실제 C++ 코드로 작성해보면 다음과 같다.
const float v1Length = sqrt(v1X * v1X + v1Y * v1Y);
const float v2Length = sqrt(v2X * v2X + v2Y * v2Y);
const float dotValue = v1X * v2X + v1Y * v2Y;
// 소수점으로 계산하기 때문에 조금 초과하거나 모자랄 수 있다.
float cosValue = dotValue / (directionLength * toTargetDirectionLength);
cosValue = clamp(-1.0f, 1.0f, coasValue);
// api에 따라 오일러 각으로 나올 수도 있다.
const float angle = acos(cosValue) * (180.0 / PI);
- 사용 사례
@ AI 시야
AI의 방향과 AI에서 다른 타겟에 대한 방향을 알고 있으면 각도를 구할 수 있고, 이 각도를 적절히 제한함으로써 시야를 구현할 수 있다.
@ 편도 트리거
트리거는 보통 충돌하면 이벤트를 발생시키지만 트리거에 방향을 앞방향으로 두면, 플레이어가 앞방향으로 진행하고, 트리거에 충돌했을 때만 특정 이벤트를 수행할 수 있다. 예를 들어 동굴을 빠져나와 새로운 곳을 발견했을 때 텍스트로 띄워줄 수 있다. 반대로 동굴에 들어갈 때는 텍스트가 뜨지 않는다.
@ 객체와 상호 작용
객체(문, 보물 상자 등)의 거리와 플레어가 해당 객체를 바라보는지 내적으로 알 수 있고, 그에 따라 상호 작용 키 UI를 띄워줄 수 있다.
* 내적과 외적 활용하기
문제 1. 플레이어와 몬스터가 존재하고, 플레이어가 바라보는 방향을 v1, 플레이어위치를 a 몬스터 위치를 b, 하늘 방향벡터를 up이라고 할때 플레이어가 몬스터를 바라보기 위해서는 어느방향으로 얼마나 회전해야할까? (단 플레이어와 몬스터가 존재하는 좌표계는 왼손좌표계이다.)

1.1. 플레이어에서 몬스터로의 방향을 v2 = b - a라고 하자.
1.2. v1과 v2를 내적하여 각도를 구한다. 단, 크기만 나오기 때문에 아직 방향은 알 수 없다.
사이의 각도를 θ라고 하면 θ = cos-1( v1 · v2 / ||v1|| ||v2||)
여기서 θ는 두 각도 중 더 작은 각도를 의미하기 때문에 최소회전으로 몬스터를 바라볼 수 도록 보장할 수 있다.
1.3. 방향을 판별하기 위해서 v1과 v2를 외적하여 그 결과인 n을 up벡터와 내적하여 관계를 알아본다.
n = v1 × v2 = (v1y*v2z - v1z*v2y, v1z*v2x - v1x*v2z, v1x*v2y - v1y*v2x)
n · up > 0
: n과 up이 같은 방향이기 때문에 왼손법칙(왼손좌표계이므로)에 의해서 플레이어가 반시계 방향으로 회전해야한다.
n · up < 0
: n과 up이 다른 방향이기 때문에 왼손법칙(왼손좌표계이므로)에 의해서 플레이어가 시계 방향으로 회전해야한다.