물체의 사이즈 변환
사이즈 값이 0보다 작으면 좌표축에 반전
호모지니어스 좌표가 들어감

물체의 평행이동

회전축: 어느축을 기준으로 회전할지 결정
회전각: 회전축에서 얼마나 회전할지의 값
(2D 회전과 다르게 원점을 기준으로 회전하는 것이 아님)
회전방향 기준은 CCW (반시계방향)



y축 기준으로 회전하는 피라미드 기반 프로그램
스케일링을 먼저 적용하고, y축 기준 회전 적용
키 입력으로 scale factor 변경

glm::vec3 vecScale = { 1.0F, 1.0F, 1.0F };
GLfloat mat[16] = { // 단위행렬
1.0F, 0.0F, 0.0F, 0.0F,
0.0F, 1.0F, 0.0F, 0.0F,
0.0F, 0.0F, 1.0F, 0.0F,
0.0F, 0.0F, 0.0F, 1.0F,
};
// 키 입력에 따른 scale factor 변경
void keyFunc(GLFWwindow* window, int key, int scancode, int action, int mods) {
switch (key) {
...
case GLFW_KEY_Q: vecScale.x += 0.05F; break;
case GLFW_KEY_W: vecScale.y += 0.05F; break;
case GLFW_KEY_E: vecScale.z += 0.05F; break;
case GLFW_KEY_A: vecScale.x -= 0.05F; break;
case GLFW_KEY_S: vecScale.y -= 0.05F; break;
case GLFW_KEY_D: vecScale.z -= 0.05F; break;
}
}

float theta = 0.0F;
system_clock::time_point lastTime = system_clock::now();
void updateFunc(void) {
// update the rotation angle
system_clock::time_point curTime = system_clock::now();
milliseconds elapsedTimeMSEC = duration_cast<milliseconds>(curTime - lastTime); // in millisecond
theta = (elapsedTimeMSEC.count() / 1000.0F) * (float)M_PI_2; // in <math.h>, M_PI_2 = pi/2
// update the matrix
mat[0] = vecScale.x * cosf(theta); mat[8] = vecScale.z * sinf(theta);
mat[5] = vecScale.y;
mat[2] = -vecScale.x * sinf(theta); mat[10] = vecScale.z * cosf(theta);
}
y축으로 스케일을 키운 모습

z축으로 스케일을 너무 키웠더니 물체가 잘려보임
canonical view volume을 벗어나서 나타난 현상

3D 회전 시 좌표축을 기준으로 회전하는 건 모든 경우를 표현하지 못함
오일러 각: 좌표축 중심의 3D 회전을 차례로 3개 합성
서로 다른 좌표축으로 세 번의 회전을 적용하는 방법
x축, y축, z축을 순서대로 3D 회전 진행: Rx(θ1) -> Ry(θ2) -> Rz(θ3)
오일러 각: (θ1, θ2, θ3)
각 축의 회전 각도 세개를 포함
행렬식

회전 적용 순서
x-y-z 순서의 회전과, y-x-z 순서의 회전 결과는 전혀 다름
unique하지 않음
전혀 다른 오일러 각으로 표현해도 회전 결과는 같을 수 있음
(90°,90°,0°) == (0°,90°,90°)
이에 대한 문제를 해결하기 위해 쿼터니언 도입
변환을 적용하는 가장 효과적인 방법
Scaling - Rotation - Translation 순서로 적용
만약 Translation 이후 Rotation을 하면 위치가 엇나가버려, Translation을 한 번 더 해줘야 원래 위치에서 회전한 결과가 나타남
3D 변환의 경우에도 마찬가지로 Scaling - Rotation - Translation 순서로 적용
p' = T(dx,dy,dz) ∘ Rz(θ3)∘Ry(θ2)∘Rx(θ1) ∘ S(sx,sy,sz) ∘ p
주어진 좌표 p에 A-B-C 순서대로 변환 적용
p' = C B A p = (C (B (A p)))
행렬을 미리 계산하여 좌표에 연산해도 똑같은 결과
M = C B A
p' = M p
S(1/sx, 1/sy, 1/sz)

T(-dx, -dy, -dz)

(스케일 변환은 없다고 가정)
호모지니어스 좌표의 4x4 행렬에서
주어진 좌표를 회전하는 부분은 좌상단 3x3
평행이동하는 부분은 우측 3x1
회전행렬을 R이라고 한다면,
호모지니어스 좌표 관점에서 벡터만 고려 시 w가 0이 되며
4x4 행렬에 벡터를 곱하는 것과 R 부분만 곱하는 것과 같음

R 행렬에 unit vector를 곱하면 각 u축,v축,n축에 대한 새로운 unit vector가 나타남

u,v,n은 서로 직교하는 basis vector
u∘u = v∘v = n∘n = 1
u∘v = v∘n = n∘u = 0
R 행렬의 transpose 행렬
R 행렬을 대각선으로 뒤집은 transpose 행렬은 R 행렬의 역행렬
R^(-1) = R^T
