-
3D 좌표, 투영관련@ 16. 1 ~ 17. 1/면접관련 2016. 12. 21. 00:47투영변환
클리핑이란 : 뷰 좌표계 중 일부를 클립하는 역할을 한다. 이떄 잘라버리는 부분은 카메라에서 보이지 않는 부분이다.
카메라에서 보이지 않는 부분을 삭제한 육면체 영역을 뷰 프러스텀이라 한다.
뷰 프러스텀을 정규 뷰 볼륨이라하는 각 정점 좌표가 정규화된 정육면체로 변환하는 것이 바로 프로젝션 변환이다.
근평면보다 커야 할 원평면이 결과적으로 같은 크기가 되므로,
뷰 프러스텀을 무리하게 정육면체 모양으로 찌부러뜨린다고 생각하면 정규 뷰 볼륨에서는 원평면에 가까워지면 가까워질수록..
오브젝트의 응축도가 높아진다. 반대로 근평면에 가까워질수록 비율적으로는 커진다. 이런 프로젝션 변환 방법을 원근투영이라한다..
**오클루전 컬링 : 카메라에서 보이지 않는 오버드로된 부분의 그리기 처리를 생략할 수 있다.
직교투영 : 직교투영의 뷰 프러스텀은 직육면체 모양으로..근평면과 원평면의 크기에 차이가 없다.
원근투영하고 달리 변환해도 원근법 효과는 나타나지 않는다. 시야각이라는 개념도 없다.
프로젝션 변환의 결과 정규 뷰 볼륨상태까지 이르게 되면 2D로의 변환은 쉽다. 정규 뷰 볼륨에 대해 뷰포트 변환이 이루어지고, 2D의 윈도우 좌표계
또는 스크린 좌표계로 변환한다. 이는 단순히 z값을 빼고 x, y값만 남긴 후 스크린 크게에 맞게 스케일을 변환하는 것이다. 떨어져 나간 z값의 저장소는
z버퍼라는 곳으로 뷰 공간에서 오브젝트의 전후 관계를 판정하는 심도 테스트에 쓰인다.
뷰 변환으로 뷰 좌표계로 변환된 지오메트리는 이번에는 프로젝션 변환에 의해 클립공간으로 바뀐다.
클립 공간의 클립 좌표계에서 정규 뷰 볼륨이 생기기 전에 정규 뷰 볼륨의 좌표계인 정규화 디바이스 좌표계로 변환하는 단계가 끼어있다.
(뷰 -> NDC 좌표계 변환 -> 투영좌표계)
이 변환을 원근분할..이라고 한다..
클립 좌표계의 좌표는 x, y, z 외에도 w라는 네번째 성분을 가진다. w가 커질수록 xyz가 작아지고 w가 작으면 xyz가 커진다.
클립좌표계는 4차원 좌표로 표현된다. 이러한 좌표계를 동차좌표계라 한다. 클립좌표계를 원근분할하여 w 성분이 1이 되어 무시할 수 있게된
시점에서 겨우 4차원이 아닌 3차원 좌표로서 정규화 디바이스 좌표계를 얻을 수 있다는 것이다.
동차좌표계의 좌표에서는 각 성분끼리의 비율만 의미가 있다.
동차좌표 (x,y,zw)로 부터 대응하는 직교좌표를 산출해내려면 w로 다른 성분을 나누어주면 된다.
w 0은 방향, 1은 위치 점광원과 방향성 광원을....여기에 표현이 가능하다
변환종류
1. 선형변환 :
기저변환 : 좌표의 변환, 좌표계의 변환
평행이동 : 평행이동은 3x3행렬로는 부족하고 동차좌표를 이용해서 벡터를 4차원으로 확장한 후에 4x4행렬과 곱한다.
실제로 의미있는 부분은 directx기준 4x3까지이다 4x4의 행은 단순히 w성분을 보존하며 결과에 영향안줌(여기서 영향없음)
회전 : 실제로 회전은 3x3행렬이면 충분하다. 4번째들은 항상 같으니까....
회전행렬은 단순히 전치하면 회전된 상태에서 원래상태로 돌아오는 변환을 나타내는 역행렬을 얻을 수 있다.
스케일 : 스케일도 마찬가지로 3x3행렬로 표현이 가능하다. 11, 22, 33 xyz ..
월드 행렬 = 스케일 + 자전 + 이동의 계산으로 누적된
월드행렬을 원래 각각의 변환을 분해하여 추출할 수 없을까?
** 스케일, 이동을 뽑은 회전만 남은 행렬은 모델 좌표계의 정규화된 벡터를 월드 좌표계로 표현한 벡터로 변환한다.
그리고 각 열이 그대로 월드 좌표계상의 벡터가 된다. 예를 들어 모델 좌표계의 기저백터 Vx = (1, 0, 0)을 이 행렬로 월드 좌표계의 벡터
Wx로 변환한다면..음..회전행렬의 R11 R12 R13이 Wx와 같다. w성분이 0이므로.(회전행렬 4x4 기저벡터도 1*4)
**그래서 월드 좌표게에서도 어떤 모델 좌표계의 기저벡터를 월드 좌표계로 나타낸 벡터를 알고 싶을때 모델 변환 행렬의 행을 가져오기만 하면된다.
평행이동은 어차피..4x4에 있음..
스케일은 행렬의 11 22 33이니까 그걸 뽀ㅃ아서...
vx = Sx11, Sx12, Sx13
인데..여기서
|vx|^2 = Sx^2 11^2, Sx^2 12^2, Sx^2 13^2 이렇게 각각 다 제곱해놓으면..
= Sx^2(11^2 + 12^2 + 13^3)
Sx^2만 따로 뺄 수 있고..
어쩄든..아휴...모델 월드변환은 기저 변환을 하는 것..?
월드행렬에서 원래 모델 좌표계에서의 x축 방햐을 알려면 모델 변환 행렬의 1행을 보면 된다..(다이렉트 기준..)
모델 좌표계의 x축을 나타내는 벡터를 모델 변환해서
결국..모델을 제작할때 모델 좌표의 어딘가의 축 쪽을 향하도록 결정하고 만들면 모델 변환행렬을 참조하기만 해도 월드 공간 내에서의 모델의 방향을
알수있어 도움이 된다.
음..어쩄든 결론..회전 행렬이란?(뽑아서 남은..) 변환 전 좌표계에서 보면 변환 후 좌표계의 기저벡터를 행에 늘어놓은것이다..
월드 -> 뷰 좌표계로 변환
먼저 카메라가 새로운 원점이 되니까 이때 평행이동 행렬은 카메라의 위치 좌표에 -값을 넣은 행렬이다.
다음으로 카메라 방향으로의 회전을 나타내는 행렬을 구해보자
각각의 축들을 외적으로 찾고... 먼저 첫 축을 찾는것은..
P(카메라가 바라보는 시선의 끝점)에서 C(카메라의 월드자표)로 향하는 벡터를 정규화하여 단위벡터로 하면 뷰 좌표계의 z축 기저벡터를 얻을 수 있다.
시선의 끝점은 어떻게 구하지...
그리고 U(업벡터)가 있으니까..z축 기저구하고 그거랑 U랑 외적하면 x가 나옴...각각 외적하면 다 나옴..카메라 기준 x,y,z가
으휴..책봐야함..
원근투영 변환
근평면을 n 원점으로부터 원평면 f라고하면..
아휴...
직교투영은..변환 결과는 똑같은 정규 뷰 볼륨인데..변환전 공간은 근평면과 원평면의 크기가 서로 다른 뷰 프러스텀이 아닌 단순한 직육면체임..
아쉽알..진짜..
오일러각 : 3차원 회전축의 회전행렬을 사용하는데...곱하는 순서에 따라 만들어지는 회전이 완전히 달라진다.
(z - x - z처럼 3축 전체의 회전을 사용하지 않는 회전순서도 널리사용된다고 하네...)
단순하고 이해하기 쉬우나...
짐벌락 : 오일러각을 이용한 회전(순서가 있는 3회의 회전축 회전)
첫번째 회전과 세번쨰 회전의 두개 축이 거의 일치하여 자유도가 2축으로 한정되는 사태를 이야기함..
아휴..사원수의 장점..
: 짐벌락 발생하지 않음.
: 회전행렬보다 점유메모리가 적음..계산부하도 적음..
: 두개 회전사이의 매끄러운 보간이라..
시...이게 다 뭔소리냐 진짜..
시..직교투영 조금 이해했다 간다..
먼저 직교투영을 하려면.
하....
왼쪽에 있는 직육면체가 평행이동하여 그 중심이 원점과 일치되도록하고..그런다음에..크기를 -1 -1 0 ~ 1 1 1 로 변환한다.
그래서..행렬 자체가
P = 스케일 * 이동인데..
기본적으로 중앙이 오려면.. 원래 회전은 필요없다..투영에선..
.
..하 시바..다시 정리..
투영에서 x,y의 범위가 -1 ~ 1 인이유는 소실점 자체를 중앙에 두기 위함이다.
그럼왜 z는 0 ~ 1인가..2차원 변환을 위한 사전작업..0 ~1범위에 한정시키는것으로 비율에 따른 x,y변환을 유도한다?
최종정리
동차좌표계 : 차원을 한단계 높이는 좌표계를 이야기한다.
예를들어 2차원 좌표계에선 x, y좌표로 나타나는데 동차좌표계로 변경을 하면 성분이 3개로 늘어나면서
x, y -> (w * x, w * y, w) // w != 0
이런식이 나오게 된다.
일단 0 아닌 임의의 수(w)를 정하고 그 값을 x, y에 각각 곱한다. 그리고 마지막 성분은 그 임의의 값(w)을 그대로 쓰는 것이다.
따라서 직교 좌표계의 한 점은 다수의 동차 좌표계 점들로 대응될 수 있다. 가장 간단한 형태는 w가 1인 경우로
직교 좌표계 점의 성분을 그대로 가지고 마지막 성분으로 1을 추가한 것이다. (x, y, 1)
거꾸로 동차 좌표계 점은 아래와 같이 직교 좌표계 점으로 대응이 된다. x, y, w -> x/w, y/w
만약에 위에 x, y, 1이라면 단순히 x, y라고 취하면 된다..
위에서 이야기 한것 처럼 하나의 직교좌표계는 다수의 동차좌표계로 대응이 된다. 예를들어 동차 좌표계의 1, 1, 1, / 2, 2, 2 / 3, 3, 3 모두
직교좌표계의 1, 1을 나타낸다.
2,3,w의 성분이 있을때 직교좌표계로 대응시키면 2/w, 3/w가 되는데.. w값이 0에 점점 다가갈수록 직교좌표계에서는 점점 멀어지게 된다 ;
w가 0이 되면 비로소 무한대의 표현..즉 방향을 나타내는 벡터로 됨..점이 아님 점은 w가 1임
비로소 정리를 하면 3차원 아핀 공간에서는 점과 벡터가 공존하는데 이들을 표현하는 방법이 동일하여 반드시 점인지 벡터인지 명시해야만 했다.
하지만 이들을 4차원 동차 좌표계로 대응시키고 나면 점인 경우에는 마지막 성분을 1
벡터인 경우는 마지막 성분 0을 주어 구분할 수 있다.
이렇게 하면 어떤 아핀변환을 적용하든 상관없이 점은 점으로 남고 벡터는 벡터로 남게 된다 필요에 따라 얼마든지 다시 직교 좌표계로 대응시킬 수 있다.
(아핀 변환의 경우 점의 마지막 성분인 w가 항상 1로 보존된다. 따라서 w로 나머지 성분을 나누는것이 무의미(즉,,로컬, 월드, 뷰변환을 이야기함) 나눈것이 의미가 있는 변화은 바로 투영 변환을 적용했을때다..(원근투영)
투영변환 정리..
시야각을 @라 하면 카메라에서 정규화된 화면까지의 거리 d는 tan(@/2) = 1/d로 구할 수가 있다..
d = 1 / tan(@ / 2) 이렇게 되는거임..이 d는 초점거리라고 부름..
그래서 시야각이 커지면 초점거리가 줄어들어 정규화된 화면이 카메라에게 다가오고 실제로 그려질 대상에서는 멀어짐(그려질 대상이 작아
반대로 시야각이 작다면 초점거리가 늘어나 정규화된 화면이 카메라에서 멀리 떨어지게 됨..그려질 대상에게 가까워진다는것..(그려질 대상이 커짐)
투영 변환 행렬의 마지막 열을 0, 0, 1, 0 으로 하는 이유(다이렉 기준, 책에서는 행이 0, 0, -1, 0인데 이유는 전치행렬 그리고 z값 부호문제임)는
결과로 나온 벡터의 마지막 성분이 zp가 되게 함으로써 자연스럽게 동차를 직교로 바꾸면서 z값으로 나눌수가 있으니까..
그냥 책봐라 ㅋㅋ 쉽게 설명됨..
직교투영..
크기나 길이의 왜곡을 만들지 않고 그대로 투영할 필요가 있는 경우가 있음..
원근투영과 다른점은..정규화된 화면을 가까운 평면과 동일시 한다는 사실이다. (원근투영에서는 가까운 평면과 정규화된 화면하고는 다른개념..)
(왜냐면 가까운 평면과 먼평면의 z값으로 정규화된 화면상의 물체를 그리기 때문이고..정규화된 화면은 시야각이나 초점거리에 의해서 결정되는거임)
투영변환..
그러니까 행렬 4x4쓰는 이유는 동차좌표계에 대한 행렬 곱셈 때문에 그런것이고....
(결정적으로..NDC좌표도 -1 ~ 1 -1 ~ 1 0 ~ 1 사이의 xyz값이니까..)
그리고 종횡비를 생각해서 미리 계산을 해둬야하는데..여기서 계산이란 역수를 의미한다 왜냐면 ㅁ리 적절히 늘리거나 줄여 놓아야 실제 화면에서는
정확하게 나오니까..그래서 종횡비를 계산하는데 x나 y둘중에 하나만 하면되는데..세로를 기준으로 가로를 맞추니까..
11(x에다가 종횡비 즉 세로분에 가로의 값을 d에다가 나누게 되는거지요..여기서 d는 시야각에 대한 초점거리입니다.~~ 즉 시야각에 대한 정규평면까지의 거리)
(정규화된 화면으로 투영을 하고 나면 이를 가지고 실제 화면 크기에 맞춰 느리는 작업을 해야하니까..)
그리고 z값 구할때 z의 비율울 구하는거니까..z는 가까운 평면이 0 ~ 먼평면이 1의 점을 사용하니까..
그 0 ~ 1로 비율을 맞추려면..어쩄든 계산식이..0 또는 1에 대한 연립방정식으로 풀면..
A(33)은 가까운 / 먼 - 가까운
B(4,3)은 가까운 * 먼 / 먼 - 가까운 의 식이 나오게 된다.
그리고 마지막 왜 (34)가 왜 1인줄알어? 그래야지 계산하면 w에 뭐가 들어가냐? z값 들어가지??
그럼 동차에서 직교로 바꿀떄 뭐해? 나눠주지? w로 다른 애들을 그럼 봐바..그럼 z로 나누는게 뭐야?
닮은꼴 삼각형에 의해서..비례하게 하기 위해서다..
그러니까 초점거리 : 실제 z값 = Yndc값 : 실제 Y 로 하기 위함이야...알겠느뇨..그래서 어차피 나눠야하는데 4x4쓰니까 w에 넣겠다 이거였지..
음..
'@ 16. 1 ~ 17. 1 > 면접관련' 카테고리의 다른 글
C++ 템플릿의 종류 (0) 2017.01.04 C++ 정리(게임개발자를 위한 C++ 참고) (0) 2016.12.28 포트폴리오 예상질문 (0) 2016.12.16 디자인패턴 정리 (0) 2016.12.16 객체지향? 절차지향? 정리 끝판 (0) 2016.12.16