행렬 관련 함수들. 
-> 행렬을 항등행렬로 변환해주는 함수. 어려우면 단순 행렬의 초기 값(1)이라고 생각하면 좋다. 
D3DXMatrixIdentity( D3DXMATRIX *pOut )
1 0 0 0
0 1 0 0
0 0 1 0
0 0 0 1

행렬의 크기 관련 함수. 
행렬 관련 함수들 공통 - outPut으로 받은 행렬을 먼저 항등행렬로 변환후 연산을 수행. 
X 0 0 0 
0 X 0 0 
0 0 X 0 
0 0 0 1 
각각 인자로 받은 XYZ에 값으로 비율대로 크기를 키워준다. (영향을 받는 원소는 11, 22, 33 번째)
D3DXMatrixScaling( D3DXMATRIX *pOut, FLOAT sx, FLOAT sy, FLOAT sz )

행렬의 회전 관련 함수 XYZ 
행렬 관련 함수들 공통 - outPut으로 받은 행렬을 먼저 항등행렬로 변환후 연산을 수행.


D3DXMatrixRotationX( D3DXMATRIX *pOut, FLOAT Angle )
1   0    0   0
0  cos sin  0
0 -sin cos  0
0  0     0   1
인자로 받은 각도 값을 각각  22, 23, 32, 33 에 영향을 끼친다. 

D3DXMatrixRotationY(D3DXMATRIX *pOut, FLOAT Angle)
cos  0 -sin  0
0    1   0    0
sin  0  cos  0
0    0    0   1
인자로 받은 각도 값을 각각 11, 13, 31, 33

D3DXMatrixRotationZ(D3DXMATRIX *pOut, FLOAT Angle)
cos sin  0   0
-sin cos 0   0
0     0   1   0
0     0   0   1

 

위치 관련 행렬 함수 
행렬 관련 함수들 공통 - outPut으로 받은 행렬을 먼저 항등행렬로 변환후 연산을 수행.


D3DXMatrixTranslation( D3DXMATRIX *pOut, FLOAT x, FLOAT y, FLOAT z )
1 0 0 0
0 1 0 0
0 0 1 0
X Y Z 1

 

행렬을 사용하여 회전

Update()

행렬 곱셈은 앞에 행과 뒤에 열의 수가 같아야 한다.

그런데 벡터와 행렬을 곱하려고 하는데 앞에 행과 뒤에 열의 수가 맞지 않아서 행렬 곱셈이 성립이 안된다.

해결 방법은 다음 함수를 사용하면 된다.

 

D3DXVec3TransformCoord()

-> 위치벡터를 얻어내고 싶다면 사용하는 함수.

-> 이 함수는 벡터와 행렬을 곱셈할 때 마지막 원소에 w=1으로 계산한다. 

-> 이러한 방식으로 D3DXVec3TransformCoord 함수를 다른 함수의 매개 변수로 사용할 수 있다.

 

위의 함수 말고도 다음과 같이 3D 벡터 법선을 주어진 행렬로 변환하는 함수가 있다.

D3DXVec3TransformNormal()

-> 방향벡터를 얻어내고 싶다면 사용하는 함수.

-> 이 함수는 벡터와 행렬을 곱셈할때 마지막 원소에 w =0으로 계산한다. 

 

m_fAngle += 5.f; 
D3DXMATRIX matScale, matRotZ, matTrans; 
D3DXMatrixScaling(&matScale, 0.5f, 3.5f, 0.f); 
D3DXMatrixRotationZ(&matRotZ, D3DXToRadian(m_fAngle));
D3DXMatrixTranslation(&matTrans, 400.f, 300.f, 0.f);

m_tInfo.matWorld = matScale * matRotZ * matTrans; 

for (int i = 0 ; i < 4 ; ++i)
{
	D3DXVec3TransformCoord(&m_vQ[i], &m_vP[i] , &m_tInfo.matWorld);
}

행렬의 곱셈의 순서는 중요하다.

반드시 크기(Scale) * 자전(RotZ) * 이동(Translate) * 공전(RevolutionRotZ) * 부모 순서를 지켜줘야 한다.

 

이번엔 공전을 해보자.

공전을 시키기 위해서는 공전할 행렬 한개, 부모 행렬 한개가 필요하다.

m_fAngle += 5.f; 
D3DXMATRIX matScale, matRotZ, matTrans, matRevRotZ, matParent; 
D3DXMatrixScaling(&matScale, 0.5f, 0.5f, 0.f); 
D3DXMatrixRotationZ(&matRotZ, D3DXToRadian(m_fAngle));
D3DXMatrixTranslation(&matTrans, 100.f, 100.f, 0.f); 
D3DXMatrixRotationZ(&matRevRotZ, D3DXToRadian(m_fAngle));
D3DXMatrixTranslation(&matParent, 400.f, 300.f, 0.f);

m_tInfo.matWorld = matScale * matRotZ * matTrans * matRevRotZ * matParent;
for (int i = 0 ; i < 4 ; ++i)
{
	D3DXVec3TransformCoord(&m_vQ[i], &m_vP[i] , &m_tInfo.matWorld);
}

D3DXVec3Length(방향 벡터)

-> 벡터의 크기를 구해주는 함수.

 

D3DXVec3Normalize()

-> 벡터의 정규화를 해주는 함수.

 

D3DXVec3Dot()

-> 벡터 내적 함수.

 

D3DXVec3Cross()

-> 벡터 외적 함수.

 

 

내적을 이용해서 마우스를 향해 이동

Update()

POINT pt = {}; 
GetCursorPos(&pt);
ScreenToClient(g_hWND, &pt);
D3DXVECTOR3 vMousePos = { float(pt.x), float(pt.y), 0.f };

// 마우스를 바라보는 방향 벡터
m_tInfo.vDir = vMousePos - m_tInfo.vPos; 

// 정규화
D3DXVec3Normalize(&m_tInfo.vDir, &m_tInfo.vDir);


// 내적 함수 또는 공식을 사용

// 내적 공식
float fCosTheta = m_tInfo.vDir.x * m_tInfo.vLook.x + m_tInfo.vDir.y * m_tInfo.vLook.y; 

// 내적 함수.
float fCosTheta = D3DXVec3Dot(&m_tInfo.vDir, &m_tInfo.vLook); 

float fAngle = acosf(fCosTheta);
 	
if (m_tInfo.vPos.y < vMousePos.y)
	fAngle *= -1.f; 

m_tInfo.vPos.x += cosf(fAngle) * 5.f; 
m_tInfo.vPos.y -= sinf(fAngle) * 5.f; 

Init()

점 찍기

점 기준으로 세팅을 해줘야 한다.

왜냐하면 만약 위치 값까지 잡혀있다면 자전이 아닌 공전이 나오기 때문이다. 

// 좌상단 
m_vP[0] = { -m_tInfo.vSize.x * 0.5f, -m_tInfo.vSize.y * 0.5f, 0.f };

// 우 상단
m_vP[1] = { m_tInfo.vSize.x * 0.5f, -m_tInfo.vSize.y * 0.5f, 0.f };

// 우하단 
m_vP[2] = { m_tInfo.vSize.x * 0.5f, m_tInfo.vSize.y * 0.5f, 0.f };

// 좌하단
m_vP[3] = { -m_tInfo.vSize.x * 0.5f, m_tInfo.vSize.y * 0.5f, 0.f };

 

회전 행렬 공식

Q.x = X * cos@ - Y * sin@; 
Q.y = X * sin@ + Y * cos@;

 

 

Update()

회전 행렬 적용

for (int i = 0 ; i < 4 ; ++i)
{	
	m_vQ[i].x = m_vP[i].x * cosf(D3DXToRadian(m_fAngle)) - m_vP[i].y * -sinf(D3DXToRadian(m_fAngle)); 
	m_vQ[i].y = m_vP[i].x * -sinf(D3DXToRadian(m_fAngle)) + m_vP[i].y * cosf(D3DXToRadian(m_fAngle)); 
	m_vQ[i] += m_tInfo.vPos; 
}

 

Render()

사각형 그리기

MoveToEx(hDC, m_vQ[0].x, m_vQ[0].y, nullptr); 

for (int i = 1; i < 4;++i )
	LineTo(hDC, m_vQ[i].x, m_vQ[i].y); 
    
LineTo(hDC, m_vQ[0].x, m_vQ[0].y);

먼저 DirectX9 환경에서 작업을 하려면 SDK를 설치해야한다.

https://www.microsoft.com/en-us/download/details.aspx?id=6812

 

DirectX SDK - (June 2010)

Download the complete DirectX SDK, which contains the DirectX Runtime and all DirectX software required to create DirectX compliant applications.

www.microsoft.com

 

위에 사이트에서 파일을 다운 받으면 다음과 같이 파일이 생긴다.

파일을 클릭 후에 설치를 진행하다보면

이러한 창이 생기는데 문제가 발생하면 해당 회사에 정보를 보낼 것인지에 대한 것이니

Yes 또는 No 둘 중 아무거나 선택해도 상관없다.

 

다음을 누르게 되면 위와 같은 화면이 나오게되는데 X표시 되어있는 것은

설치를 안해도 되지만 혹시모르니 X 옆의 화살표를 누른 뒤 첫번째 칸에 있는 것을 눌러서

추가를 하자

 

그런데 간혹가다 설치를 하고나서 다음과 같은 오류가 발생하는 경우가 있을 수가 있다.

이유는 SDK를 설치하는 도중에 이미 다운 받아져 있는 파일과 서로 충돌이 일어나서 그런 것이다.

해당 문제를 해결하려면 시작 / 명령 프롬프트를 실행하고 콘솔 창에 다음과 같이 입력한다.

 

MsiExec.exe /passive /X{F0C3E5D1-1ADE-321E-8167-68EF0DE699A5}

MsiExec.exe /passive /X{1D8E6291-B0D5-35EC-8441-6616F567A0F7}

 

위에 문구를 입력하게되면 

 

현재 설치되어 있는 아래 두 가지의 패키지가 삭제가 된다.

 

Microsoft Visual C ++ 2010 x86 재배포 가능 패키지

Microsoft Visual C ++ 2010 x64 재배포 가능 패키지

 

삭제 후에 다시 설치를 진행하면 정상적으로 설치가 완료된다.

 

설치가 완료된 후에는 해당 프로젝트에 들어가서 프로젝트 속성을 클릭한 다음에 VC++ 디렉터리로 이동한 후에

포함 디렉터리에는 설치 폴더에 있는 Include 폴더를

라이브러리 디렉터리에는 Lib 폴더를 포함 시켜준다.

그 다음에 stdafx.h 또는 framework.h에 가서 다음과 같이 헤더를 추가해준다.

(기본적으로 추가되어 있는 헤더보다 아래에 추가해야한다!!)

헤더파일까지 추가를 완료했으면 정상적으로 작동할 것이다.

+ Recent posts