이제 직접 띄운 3D 물체를 한번 공간 상에서 움직여 보자.. 초반 포스팅에 보면, 랜더링 파이프 라인에 대해 적었는데, 이제야 로컬 좌표에 기본 0,0,0에서의 물체만 보는 것이 아니라, 월드 뷰 행렬에 대입하여, 물체를 움직여 볼 수 있겠다...


먼저 이 예제는 태양, 지구, 달의 자전과 공전에 대한 예제이다. 그러니 메쉬가 3개 필요하다. 구체이기 때문에 CreateSphere 로 구를 만들 것이다. 그리고 특별히 텍스쳐는 로드 하지 않는다.


버텍스 포멧으로는, 포지션 값과, 디퓨즈 색 값을 받도록 설정한다..


그리고, 먼저 Temp 지구와 태양을 선언하여 그 변수를 이용해 구를 만드는데, 그 이유는 색을 적용시키기 위해서이다. 지금 CreateSphere로 구를 만들면, 색 정보가 없는 버텍스 버퍼로 구를 만들었을 뿐이다. 그렇기 때문에 색 정보를 주기 위해서 미리 템프로 만들고, 색 정보 FVF 포멧을 가진, 클론 메쉬를 만들 것이다. 텍스쳐 맵핑을 하려면, 이 단계를 생략하고, 바로 지구와 태양 메쉬를 구로 생성한 후에 로드한 텍스쳐를 맵핑하면 될 것이다.

 


이제, 생성된 템프지구 메쉬로 클론메쉬FVF 함수를 통해,  우리가 정의한 FVF 포멧을 가진 구 메쉬를 생성한다. 마지막에 짤린 변수는 초기에 선언해준 메쉬이다. 그 후에 지구 메쉬의 버텍스 버퍼를 없어온 후, 그 버텍스 버퍼에 락을 걸로, 디퓨즈 색을 파랑으로 설정하고 언락을 한다.


태양 메쉬도 같은 방법으로 하여, 노란색 디퓨즈 값을 넣어준다.


이 것 외에는 설정할 것이 없기 때문에 바로 랜더로 와서, 일단 뷰 행렬을 넣어준다. 현재는 고정이지만, 키보드 인풋이나 머 다른 요인으로 저기 제일 첫 Vector3의 값을 조정하면 위치가 바뀌고, 2번째 값은 바라보는 방향, 3번째는 업벡터이다.

카메라 값에 왜 포지션, 룩엣, 업 벡터가 필요한지는 이전에 말했으니 넘어가도록 하고, 그렇게 정해진 값을 SetTransform하여 D3DTS_VIEW에 넣어준다. 기본적으로 우리가 넣는 행렬값은 월드, 뷰, 투영 인데.. 사실 투영은 초기화 할 때 한번 넣어주면 잘 변하지 않는다. 뷰는 카메라 이동이 있을 때 넣어주기 때문에, 루프가 돌 때 마다 위치나 보는 방향을 갱신해서 넣어주면된다..


 이제 실제 메쉬에 행렬을 곱하는 부분이다. 태양을 Y축으로 회전 시키고, Scale을 크게 늘렸다. 그리고 곱하는 순서는 스케일 회전 순이다.. 3D의 행렬 연산에서는 곱하는 순서가 아주 중요하다. 왜냐하면 뒤의 연산에 앞의 연산이 영향을 받기 때문이다. 잘 감이 오지 않는다면, 그냥 기본적이던 모델링이 우리의도에 따라 어떻게 변하는지 생각하면된다. 보통 스케일, 로테이션, 트렌스레이션 순으로 크기, 회전, 이동 순으로 곱하게 되는데, 그렇게 되면 모델링은 로컬 좌표를 기준으로 크기가 커지고, 거기서 회전을 한 후 우리가 정한 월드 좌표로 이동을 한다.

 하지만 그 순서가 바뀌어서 회전을 한후, 스케일이 커지고, 이동을 하면.. 머 영향이 없을 수도 있다. 스케일은 보통 x,y,z 같은 크기로 키우기 떄문이다. 하지만 한 축이라도 같은 값이 아니라면, 뒤의 연산에 큰 영향을 끼친다. 그리고 사실 회전과, 이동 이 큰 영향을 받는다.. 순서가 중요한데, 이동하고 회전을 하느냐, 회전을 하고 이동하느냐 이 것에 따라 결과가 크게 차이난다..

 


그럼 먼저, 지구를 보자, 행렬을 Y 축 회전 행렬 2개, 위치 이동 행렬 1개, 이렇게 있다. 우리는 먼저 생각할 것이, 이 이동 행렬의 영향은 로컬 좌표계를 기준으로 이루어 진다는 점이다. 처음에 메쉬가 생성되게 되면 로컬 0,0,0을 기준으로 우리가 만든 버텍스들의 각 좌표가 월드상에 펼쳐져 있게 된다. 그 상태에서 위의 회전 부터 곱해진 순서대로 생각해보자...

 먼저 자전 회전을 하였다. 그렇게 되면, Y축을 기준으로 일정양만큼 회전하였다. 제자리에서 어느정도 각도록 돌았을 것이다. 그 다음에 위치 이동이다. 로컬 좌표를 기준으로 z축방향으로 12 만큼 갔을 것이다.. 여기서 예제를 돌리면서 깨달았는데, 나는 처음에 돌리는 Y축회전이 공전일 줄 알았다. 그래서 축 자체가 돌아갔기 때문에, 그 후에 내가 원하는 방향으로 한번만 이동한후, 또 한번 더 돌면 그 때 자전이 될 거라고 생각했었다.. 그런데 행렬을 하나씩 제거하면서 연산을 하자, 마지막 행렬이 빠지면, 제자리에서 자전만 되었다.  
 즉, 로컬축이 돌아가는 것이 아니라, 회전 행렬을 그냥 로컬 축의 기준점을 기준으로 회전 이동 의 영향만 준다는 사실이다. 항상 쓰면서도, 헷갈렸는데 ( 물론, 대부분 의도한 대로 잘 움직였다. s*r*t 순의 연산 순서만 지키면 말이다.. )
오늘 제대로 정리한 것 같다. 

 다시 돌아와서, 제자리에서 Y축 회전 후, z축 방향으로 12만큼 이동 후 다시 Y축회전이 되면 바로, 로컬의 기준 점을 기준으로 z축으로 12만큼 가있기 때문에, 제자리 회전이 아니라 콤퍼스의 끝 점 처럼 원을 그리면서, 쭉 돌게 된다. 그래서 태양 주변을 도는 공전 회전이 완성 되는 것이다.


그리고 위의 것은 달의 모습이다. 이 것은 한번의 연산이 더 있다. 바로, 지구의 행렬 값도 받은 상태에서 움직이는 것이다. 그래서 처음 3개의 행렬의 연산 만으로는 그냥 달이 태양 주변에서 공전을 했겠지만, 공전이 된 상태에서 다시 지구의 위치 좌표로 움직이고, 그 다음에, 지구가 돈 방향만큼 더 돌기 때문에, 달이 지구를 도는 속도는 지구가 태양을 도는 속도보다 빠르게 되는 것이다.

컴파일하면 다음과 같다...

 



계속 태양도 돌고, 지구도 돌고, 달도 돈다. 그리고 지구는 태양 주변을 돌고, 달은 지구 주변을 돈다...

물론 처음보면, 이 개념자체가 잘 이해가 안될 수도 있다.. 물론 나도 처음엔 그랬다. 하지만 자꾸 손으로 왼손 좌표계를 만들고 회전을 적용시켜보면 언젠가는 행렬의 연산이 쉬워지는 날이 올 것이다.
Posted by 바람처럼..
|