최상단 광고

2012년 4월 9일 월요일

직교투영 Picking

원근투영은 물체의 정점이 시점으로 수렴되지만, 직교투영은 그렇지 않죠. 

따라서 직교투영에서 피킹에 사용할 반직선은 노멀라이즈한 시선방향벡터를 투영평면상의 마우스 위치만큼 옮기면 간단하게 구할 수 있습니다. 

OpenGL의 경우 직교투영행렬의 [0,0], [1,1] 은 다음과 같이 생겨먹었습니다. {D3D도 마찬가지겠군요.} 

OrthoMatrix[0,0] = 2/(Right-Left) 
OrthoMatrix[1,1] = 2/(Top-Bottom) 

투영평면에서 뷰볼륨에 정규화된 마우스의 위치는 다음과 같이 구할 수 있죠. 

aX = (마우스 X * 2.0 / 화면 너비)-1.0 
aY = -(마우스 Y * 2.0 / 화면 높이)-1.0 

정규화되지 않은 마우스 위치는 OrthoMatrix[0,0], OrthoMatrix[1,1]을 aX,aY에 각각 곱해주시면 되겠죠?? 

bX = aX * OrthoMatrix[0,0] 
bY = aY * OrthoMatrix[1,1] 

이렇게 얻어진 bX와 bY를 이용해 반직선의 시점과 종점을 만들어 보죠. 

시점 = (bX, bY, 0) 
종점 = (bX, bY, -1) {D3D에서는 (bX, bY, 1)이 되겠죠??} 

이 정점을 뷰변환행렬의 역행렬로 변환시키면 세계공간에서 피킹에 사용할 반직선을 얻을 수 있습니다. 

뷰좌표계의 U, V, N 벡터를 알고 있다면... U벡터를 bX만큼 스케일, V벡터를 bY만큼 스케일 해서 얻어진 좌표에 카메라 시점벡터를 더한 좌표를 원점으로, 다시 여기에 N벡터를 뺀 좌표를 종점으로 하는 반직선을 만들어 쓰시면 되죠. {D3D에서는 N벡터를 더해야... ^^} 

더 간단하게 해결하시려면 피킹하려는 물체와 시점의 거리를 아주 길게 만드세요. 그러면 직교투영에서의 실제 반직선과 비슷하게 맞아들어가기 때문에 그럭저럭 사용할 수는 있습니다. 물론 현재 직교투영으로 보여지는 이미지와 같은 크기로 보여지도록 반직선을 계산할 원근투영의 Fov를 잘 설정하셔야 하지만요~ ^^; 

Fov = arctan( OrthoMatrix[0,0] / 카메라 거리 ) 

제가 만들어 쓰는 맵툴도 직교투영과 원근투영을 바꿀 수 있지만 어차피 내부에서만 쓸 거라... 맵작업 하시는 분들 께 직교투영할 때는 카메라를 멀리 빼서 사용하라고 압력을 넣고 있습죠~~ ^^;; (음... 이 글을 보면 안되는데~~ 흐흐~~) 


댓글 없음: