Axis-angle rotation, 혹은 Rodrigues formula란, 축과 각이 주어졌을 때 어떤 벡터를 해당 축에 대해 해당 각만큼 회전시킨 벡터를 구하는 과정이다. v를 n을 기준축으로 시계 방향으로 세타만큼 회전시킨 v'을 구하는 과정을 살펴보자. (축 n은 단위벡터라고 가정한다. 단위벡터가 아닐 경우 그냥 단위벡터로 만들어주면 된다) v를 n에 정사영 내려 p를 구할 수 있고, v - p = e이므로 e도 구할 수 있다. v' = p + e'인데, e'은 f와 e를 축으로 하는 평면에 대해 e를 세타만큼 반시계 방향으로 회전시킨 벡터이다. 이는 우리가 구할 수 있는 값이다. f를 y축, e를 x로 두고 생각하자. 위 그림에선 세타가 둔각이지만 이해를 돕기위해 세타가 예각이라고 해보자. 그..
Frustum Culling이 무엇인가에 대해서는 이 포스트에서 다루고 있다. Frustum Culling을 구현하기 위해 가장 중요한 것이 어떤 정점이 어떤 평면의 어느 방향에 있는지 (법선벡터의 양의 방향에 있는지 법선벡터의 음의 방향에 있는지) 를 빠르게 판별하는 것이다. 그래야 잘린 피라미드들의 각 면에 대해 해당 연산을 진행하여 해당 정점이 카메라 내부에 있는지 바깥에 있는지를 판별할 수 있다. 크기가 1인 벡터 n을 법선벡터로 가지는 평면이 존재할 때, 어떤 점X를 중심으로 하는 구가 해당 평면의 어느 방향에 위치하고 있느냐를 판정해보자. (파이프라인에선 구가 평면에 겹치기만 해도 어쨌든 구 일부가 카메라 시야 안에 들어오므로 렌더링한다) 우선, 평면에서 좌표계 원점까지의 거리 d를 구한다. ..
앞서 우린 어떤 2d 벡터와 각 변이 축과 직사각형의 Collision 판정을 위해 Line-AABB Intersection이라는 방법을 사용할 수 있음을 배웠다. 이전엔 이 방법을 보다 넓은 범위로 확대해, 3차원 직육면체와 선의 충돌을 계산할 수 있도록, 또 물체가 축과 평행한 변을 가진 AABB(Axis Aligned Bounding Box)가 아닌 일반적인 직육면체이더라도 계산할 수 있도록 확장해보자. 일단 2D line aabb intersection을 3D로 변환하는 과정은 다음과 같다. https://sudhamr.wordpress.com/2019/05/01/week-12/ Week 12 : AABB-Ray Intersection The next intersection test that we..
그동안 앞선 글들에서 우린 변환행렬들과 벡터의 행렬곱을 이용한 벡터의 물리적 변환들(회전, 크기변화, 이동)을 살펴보았다. 또한 행렬곱을 이용해 좌표계를 변환하는 법에 대해서도 알아보았다. 이번 글에서는 이 두 내용이 본질적으로는 같은 내용이라는 것을 설명하고자 한다. 우리는 행렬에 벡터를 곱하는 행위를 정의역과 치역이 모두 벡터인 어떤 함수라고 생각할 수 있다. 즉, 행렬곱은 선형변환이고, 선형변환은 행렬곱이다. (선형변환의 정의는 아래와 같으며, 임의의 행렬 A에 대해 T(x) = Ax가 항상 이를 만족함을 알 수 있다.) 선형사상(=행렬곱)은 기하학적으로 해석이 가능하다. 이를 이해하면 우리는 그동안 다뤄왔던 다양한 종류의 변환행렬들이 왜 그런 형태를 하고 있는지도 이해할 수 있다. 예시를 보면 직..
3차원 공간에 있는 오브젝트의 가장 기본적인 물리적 연산 세가지가 바로 Translation(이동), Rotation(회전), Scaling(크기 변환)이다. 그동안 앞선 글들에서 우리는 이 세가지의 기본 연산을 행렬곱으로 표현할 수 있음을 배웠다. 그렇다면 이 변환들을 해주는 행렬들을 미리 다 곱해놓으면 단 한 번의 행렬곱으로 모든 물리적 연산을 표현할 수 있지 않을까? 실제로도 그렇다. 그러나 여기서 주의해야 하는 것은 어떤 연산을 먼저 하는지가 중요하다는 점이다. 위 사진처럼 물체를 이동시킨 후 회전시키고 그 다음 크기를 변화시키면 우리가 원하는 결과가 나오지 않았음을 알 수 있다. 때문에 우리는 항상 Scaling, Rotation, Translation의 순서로 연산을 해주어야 한다. 이 연산은..
3차원 회전에 대한 각 축별 회전행렬(Rotation Matrix)도 같은 원리로 도출할 수 있다. 회전방향은 마찬가지로 기준이 되는 축에 대해 반시계 방향이다. (위 식을 보면 2차원 회전행렬과 3차원 z축 기준 회전행렬이 거의 유사함을 볼 수 있다) void Matrix4x4::SetRotation(float flAngle, const Vector& v) { // Normalize beforehand TAssert(fabs(v.LengthSqr() - 1) < 0.000001f); // c = cos(angle), s = sin(angle), t = (1-c) // [ xxt+c xyt-zs xzt+ys ] // [ yxt+zs yyt+c yzt-xs ] // [ zxt-ys zyt+xs zzt+c ..
어떤 벡터의 크기를 키우거나 줄이려면 Identity Matrix의 각 열벡터에 상수배를 해준 후 Identity Matrix에 벡터를 곱해주면 된다. 이때 만약 I 대신 다른 기저벡터 좌표계에 대해 크기를 변경하고 싶다면 I 대신 그 기저벡터들을 열벡터로 가지는 행렬을 대신 사용하면 된다.