피킹
화면을 클릭했을때 우리는 니어를 클릭한것
니어 - 카메라 를 하면 하나의 방향벡터(레일)을 구할수 있다. 레일과 겹치는 지형을 클릭한것이되는것.
D3DXIntersectTri() 삼각형과 방향벡터가 충돌하는지 하는지를 검사해주는 함수.
방향벡터는 위치를 가지지않음 레이pos(레이의 시작점)을 전해줘야한다. 하나의 방향벡터를 특정할수 있음
지형을 피킹 해보자.
관건은? 지형을 구성하는 3가지 점을 가져오는것
(로컬에서하는게 좋을까 월드에서하는게 좋을까?)
2D와 달리 3D는 두개의 좌표계를 사용한다(로컬과 월드) 충돌을 위해 비교를 할때 꼭 같은 좌표계에서 비교를해야한다.
로컬 스페이스 상에서 비교를하면 모두 충돌하는것으로 나온다.
빛연산 - 지형의 노말(로컬좌표를기반으로만듬)
빛의 위치(월드스페이스 기반) 빛연산을 장치가 하고있지만 잘못된 연산일 가능성이 큼
즉 니어 - 카메라의 방향벡터를 지형의 로컬 상으로 옮겨야한다.
정점이 많으면 로컬이 편하다.
GetCursorPos로 마우스의 위치를 구할수있다.
ScreenToCline로 윈도우영역에 있는 마우스의 위치로 변환할수있다. x,y좌표를 구했다 z는 니어이다.
모든 니어값은 렌더링파이프라인을 거치면 0이됨.
즉 클릭한 마우스의 뷰포트화면상의 x,y(뷰포트스페이스)z(투영 스페이스)
어떻게 x,y를 투영스페이스로 옮길수있을까
뷰포트화면상에 0,0은 -1,1 1,1은 1,-1이 된다
800,600이 1,-1 이되는 연산을 구해주면
투영스페이스상의 x,y,z,w를 구할수 있다.
이제 이행렬의 역행렬을 구한다.
로 월 뷰->투영행렬곱 , w나누기(신경쓸필요없다)-> 투
투영행렬의 역행렬을 곱해주면 뷰행렬을 구할수있다.
다음 뷰포트변환행렬의 역행렬 구하면 월드행렬구할수있다.
다음 월드 변환행렬의 역행렬 곱하면 로컬행렬 구할수 있다.
뷰스페이스에서 레이의 시작점은 0,0,0 카메라가 원점으로 초기화되기때문.
피킹 컴포넌트를 만들자
엔진 컴포넌트에 피킹클래스를 만들자.
클론없이 구현한다. Clone함수에서는 ADD_REF해주고 return this 해준다.
마우스의 좌표를 구해와주는 함수
Compute_MouseCursorPos(HWND hWnd)
마우스의 위치를 저장할 멤버변수
_float4 m_vMousePos;
Compute_MouseCursorPos(HWND hWnd)
{
포인트 구조체에 GetCurPos를 통해 좌표를 저 장하고 ScreentoClient로 클라이언트상의 좌표 로 변환해주자.(뷰포트 스페이스 상의 마우스 위치)
투영 스페이스 변환까지 변환은 - 좌표변환으로 가능하다.
뷰스페이스까지의 변환은
최소환 카메라의 tick(파이프라인에 변환행렬을 저장)이 호출된뒤에 호출되어야함
월드 스페이스변환은
파이프라인에서 뷰스페이스변환행렬을 가져와서 역행렬을 구해주자.
}
순서가 중요한이유
게임인스턴스의 틱에서 카메랄부터 투영과 뷰 구하고
마우스좌표이동
레이트틱에서 충돌을 검사한다.
현재 GameInstance는 Tick에서 Late_Tick을 호출한다 MainApp에서 분리를 위해 Late_Tick으로 분리해주자.
다시 피킹기능을 구현하기위해 컴퓨트_마우스포스로돌아오자.
mouse.x / ( winsizex/2) -1 0은 -1이되고 800은 1이됨
mouse.y / -( winsizex/2) +1 0은 1이되고 600은 -1이됨.
투영스페이스까지 변환
1.뷰포트 구조체를 서언하고
2.장치의 GetViewPort함수를 호출해주자.
3.위의 식으로 투영스페이스상의 x,y를 구하자.
4.현재 투영스페이스의 z는 0이다(니어는 0으로 표현됨.
5.w는 1이다.(w나누기를 했기때문)
투영 스페이스상의 (x,y,z,w)를 구했다.
뷰스페이스까지 변환
1.파이프라인 인스턴스를얻어오자.(엔진 내에서 사용할수있음 클라이언트는 엔진에서 외부로 내보내지않았기 떄문에 게임인스턴스를 통해 접근해야함)
월드스페이스 까지 변환
로컬로 가기위해선 어떤 객체의 월드 변환행렬이 필요함 -> 이는 클라에서 해준다.
멤버변수 두개를선언해주자.
월드 행렬상태에서의 레일과 피봇
m_vMouseRay,m_vMousePivot
뷰스페이스를 구한시점에서 피봇(카메라의 위치)는 원점이다 (0.f,0.f,0.f) 마우스피봇구했다.
레이는 마우스 - 피봇의 방향벡터 이다 피봇이 원점이므로 마우스 좌표 그대로를 넣어준다.
피봇과 레이를 뷰스페이스의 역행렬과 곱해주자.
굳이 마우스포스를 멤버변수로 보관할이유가없다 지우고 지역변수로 쓰자.
함수를 사용하자
MainApp에서 피킹의 원형 생성하자. 다음 MainApp에서 렌더러와 같이 멤버변수로 보관하자.
컴포넌트매니저에 피킹헤더 추가해주자.
플레이어를 클릭해서 이동시켜주자.
플레이어에 피킹 컴포넌트 추가해주자.
Add_Components 에서 추가해주자.
Free에서 지워주자.
이제 충돌을 구현해주어야한다.
마우스로 픽된 위치를 가져와야한다.(피킹 컴포넌트한테서 가져오자(버퍼를 건내주고 버퍼와 충돌된 위치를 가져와));
Compute_PickingPoint()
위 함수로 충돌한 위치를 받아오자.
이함수의 최종목적은 D3DXIntersectTri를 호출하는것이다.
인자로 월드행렬을 받아와서 역행렬로 만들어주자.
현재 피킹되고있는 마우스레이와 피봇을 로컬로 옮기기위해 이를 받아왔다.
멤버변수에 이를 변환하면 안됨(다른애들도 써야하니깐)
지역변수로 레이와 피봇을 만들자.
D3DXVec3TranformCoord()와 노말로 값을 곱해서 지역변수와 넣어주자.
이렇게해서 로컬에있는 레이와 피봇을 구했다.
VI버퍼에 폴리곤을 얻어오는 Get_PolygonIndices함수를 만들어주자
VI버퍼안에 NumPrimitve가 삼각형의 갯수를 보관하고 있다. Get 함수로 받아올수있게 해주자.
Get_PolygonIndices는 인자로 인덱스 번호와
VI버퍼에 멤버변수로 m_pIndices를 보이드 포인터로 선언해놓고 iOndeIndexSize에따라 쇼트나 인트로 동적할당해준다.
공간 할당했으니 값을 받아와야한다
m_pIB의 Lock을 호출해서 값을 저장해주자
memcpy로 값 복사해주자
UnLock 호출해주자.
복사생성자에서 m_pIndices 값 복사해주자.
버퍼의 Get_PolygonIndices을 구현하자.
점을 세개씩 가져와야한다.
함수명 변경Get_PolygonVertePositions
m_pVerticsPos를 터레인에서 하지말고 버텍스에서하자
for문을 통해 memcpy로 복사해주자.
Vertices를 1바이트로 캐스팅해서 넘어가게 만들었다 이주소를 다시 float_3로 캐스팅해서 값으로 넣어준다.