3D 벡터의 내적과 정규화된 내적
내적은 두 벡터 간의 각도 관계를 표현하는 값으로, 두 벡터를 곱한 후 그 결과를 더하여 계산됩니다. "내적"이라는 이름은 이 연산을 나타내기 위해 자주 사용되는 중심 점 "·"에서 유래되었습니다. 대안 이름인 "스칼라 곱"은 결과의 스칼라적 성격을 강조합니다.
수학적 공식
2D에서 벡터 a[x1, y1]와 b[x2, y2]의 내적은 다음과 같이 계산됩니다:
x1 * x2 + y1 * y2
3D에서는 벡터 a[x1, y1, z1]와 b[x2, y2, z2]의 내적은 다음과 같습니다:
x1 * x2 + y1 * y2 + z1 * z2
따라서 GameMaker에서 3D 내적은 다음과 같이 계산됩니다:
a · b = (x1 * x2) + (y1 * y2) + (z1 * z2);
정규화된 내적
정규화된 내적은 반환 값을 -1과 1의 범위로 조정하여 계산됩니다. 이는 조명 및 기타 3D 기능을 다룰 때 특히 유용합니다.
문법
dot_product_3d_normalised(x1, y1, z1, x2, y2, z2)
인수 설명
인수 | 유형 | 설명 |
---|---|---|
x1 | 숫자 | 첫 번째 벡터의 x 좌표 |
y1 | 숫자 | 첫 번째 벡터의 y 좌표 |
z1 | 숫자 | 첫 번째 벡터의 z 좌표 |
x2 | 숫자 | 두 번째 벡터의 x 좌표 |
y2 | 숫자 | 두 번째 벡터의 y 좌표 |
z2 | 숫자 | 두 번째 벡터의 z 좌표 |
반환값
정규화된 내적의 결과값을 반환합니다.
예제 코드
var x1, y1, x2, y2;
x1 = 0;
y1 = 1;
z1 = 0;
x2 = o_Player.x - x;
y2 = o_Player.y - y;
z2 = o_Player.z - z;
if dot_product_3d_normalised(x1, y1, z1, x2, y2, z2) > 0 {
above = true;
} else {
above = false;
}
위 코드는 인스턴스의 y(위쪽) 축을 따라 정규화된 벡터를 생성하고, 플레이어 객체 "o_Player"의 벡터를 가져옵니다. 마지막으로 이 두 벡터의 내적을 계산하고, 결과가 0보다 크면 변수 "above"를 true로 설정하고, 0 이하이면 false로 설정합니다.
활용 예제
- 조명 계산: 정규화된 내적을 사용하여 표면의 조명 강도를 계산할 수 있습니다.
gml var light_direction = dot_product_3d_normalised(surface_normal.x, surface_normal.y, surface_normal.z, light_vector.x, light_vector.y, light_vector.z);
- 충돌 감지: 두 벡터의 방향을 비교하여 충돌 여부를 판단할 수 있습니다.
gml if dot_product_3d_normalised(object1_vector.x, object1_vector.y, object1_vector.z, object2_vector.x, object2_vector.y, object2_vector.z) < 0 { // 충돌 발생 }
- 물체의 방향 조정: 물체가 특정 방향을 향하도록 조정할 때 사용할 수 있습니다.
gml var direction = dot_product_3d_normalised(current_direction.x, current_direction.y, current_direction.z, target_direction.x, target_direction.y, target_direction.z);
- 게임 AI: AI가 플레이어를 추적할 때 방향을 결정하는 데 사용될 수 있습니다.
gml var ai_vector = dot_product_3d_normalised(ai_position.x, ai_position.y, ai_position.z, player_position.x, player_position.y, player_position.z);
- 카메라 움직임: 카메라가 특정 물체를 바라보도록 조정할 때 활용할 수 있습니다.
gml var camera_vector = dot_product_3d_normalised(camera_position.x, camera_position.y, camera_position.z, target_position.x, target_position.y, target_position.z);