현재 작업을 특정 라이브러리에 종속 시키지 말자라는 목표로 자체타입을 정의해서 코딩을 하고 있습니다. 직접 타입을 정의해서 작업하다 보니 평소에는 DirectX API를 통해 쉽게 값을 얻을수 있었던 각종 행렬 연산, 벡터 연산등을 직접 구현해주어야 하게되었죠. DirectX API를 쓸때는 몰랐는데 이게 은근 머리가 아프네요. 제가 수학을 못하는 것도 있지만 그냥 식만 봐서 그걸 코딩으로 옮기기가 힘들더군요. ( 공부좀 해둘걸 ㅠㅠ )

밑은 Frustum을 만들때의 예입니다.

//   Projection Matrix를 생성
//   xScale     0          0               0
//   0        yScale       0               0
//   0          0       zf/(zf-zn)         1
//   0          0       -zn*zf/(zf-zn)     0
//   yScale = cot(fovY/2)
//   xScale = yScale / aspect ratio
void ev_CFrustum::PerspectiveFov( void )
{
	ZeroMemory( &m_ProjMatrix, sizeof( m_ProjMatrix ) );
	float fYScale = ev_CMath::cot( m_fFov / 2.f );
	float fXScale = fYScale / m_fAspect;
	float fQ = m_fFarDist / ( m_fFarDist - m_fNearDist );
	float fQN = -m_fNearDist * fQ;
	m_ProjMatrix[0][0] = fXScale;
	m_ProjMatrix[1][1] = fYScale;
	m_ProjMatrix[2][2] = fQ;
	m_ProjMatrix[2][3] = 1;
	m_ProjMatrix[3][2] = fQN;
}

//   View Matrix를 생성
//   xaxis.x           yaxis.x           zaxis.x			0
//   xaxis.y           yaxis.y           zaxis.y			0
//   xaxis.z           yaxis.z           zaxis.z			0
//   -dot(xaxis, eye)  -dot(yaxis, eye)  -dot(zaxis, eye)	1
//   zaxis = normal(At - Eye)
//   xaxis = normal(cross(Up, zaxis))
//   yaxis = cross(zaxis, xaxis)
void ev_CFrustum::UpdateViewMatrix( void )
{
	ev_CVector3 vecZAxis = ( m_LookAt - m_Eye ).GetNormalize();
	ev_CVector3 vecXAxis = ( ev_CVector3::UNIT_Y.CrossProduct( vecZAxis ) ).GetNormalize();
	ev_CVector3 vecYAxis = vecZAxis.CrossProduct( vecXAxis );

	m_ViewMatrix[ 0 ][ 0 ] = vecXAxis.x;
	m_ViewMatrix[ 1 ][ 0 ] = vecXAxis.y;
	m_ViewMatrix[ 2 ][ 0 ] = vecXAxis.z;

	m_ViewMatrix[ 0 ][ 1 ] = vecYAxis.x;
	m_ViewMatrix[ 1 ][ 1 ] = vecYAxis.y;
	m_ViewMatrix[ 2 ][ 1 ] = vecYAxis.z;

	m_ViewMatrix[ 0 ][ 2 ] = vecZAxis.x;
	m_ViewMatrix[ 1 ][ 2 ] = vecZAxis.y;
	m_ViewMatrix[ 2 ][ 2 ] = vecZAxis.z;

	m_ViewMatrix[ 3 ][ 0 ] = -vecXAxis.DotProduct( m_Eye );
	m_ViewMatrix[ 3 ][ 1 ] = -vecYAxis.DotProduct( m_Eye );
	m_ViewMatrix[ 3 ][ 2 ] = -vecZAxis.DotProduct( m_Eye );
	m_ViewMatrix[ 3 ][ 3 ] = 1;
}

void ev_CFrustum::UpdateFrustumPlane( void )
{
	ev_CMatrix4 viewProj = m_ViewMatrix * m_ProjMatrix;
	ev_CMatrix4 ViewProjInv = viewProj.GetInverse();
	ev_CVector3 vecZ = ev_CVector3( m_ViewMatrix.m[0][2], m_ViewMatrix.m[1][2], m_ViewMatrix.m[2][2] );

	float fNear = -( -vecZ.DotProduct( m_Eye ) ) + m_fNearDist;
	m_FrustumPlane[ FRUSTUM_PLANE_NEAR ].normal		= -vecZ;
	m_FrustumPlane[ FRUSTUM_PLANE_NEAR ].d			= fNear;

	float fFar = -( vecZ.DotProduct( m_Eye ) ) - m_fFarDist;
	m_FrustumPlane[ FRUSTUM_PLANE_FAR ].normal		= vecZ;
	m_FrustumPlane[ FRUSTUM_PLANE_FAR ].d			= fFar;

	ev_CVector3 vecVert[ 4 ];
	vecVert[ 0 ] = ViewProjInv * ev_CVector3( -1.f, -1.f, 0.f );
	vecVert[ 1 ] = ViewProjInv * ev_CVector3( -1.f,  1.f, 0.f );
	vecVert[ 2 ] = ViewProjInv * ev_CVector3(  1.f,  1.f, 0.f );
	vecVert[ 3 ] = ViewProjInv * ev_CVector3(  1.f, -1.f, 0.f );

	m_FrustumPlane[ FRUSTUM_PLANE_LEFT ]	= ev_CPlane( vecVert[0], vecVert[1], m_Eye );
	m_FrustumPlane[ FRUSTUM_PLANE_RIGHT ]	= ev_CPlane( vecVert[2], vecVert[3], m_Eye );
	m_FrustumPlane[ FRUSTUM_PLANE_TOP ]		= ev_CPlane( vecVert[1], vecVert[2], m_Eye );
	m_FrustumPlane[ FRUSTUM_PLANE_BOTTOM ]	= ev_CPlane( vecVert[3], vecVert[0], m_Eye );
}
대략 이런식으로 이전 같았으면 D3DXMatrixPerspectiveFovLH, D3DXMatrixLookAtLH, D3DXVec3TransformCoord, D3DXPlaneFromPoints 함수들을 호출해주는 것으로 끝났을 일을 일일히 코딩하고 있습니다. 덕분에 작업속도도 상당히 늦어지고 있네요. ( 요즘은 회사 일도 있다보니... )

DSLR 클럽에 올라 왔었다는 이름 모를 처자분. 일반인이시라는데 포스가 ㅎㄷㄷ~

  1. 은령 2011.01.16 20:10

    이거슨 레진님께서 친히 선별하여 소개하셨던 바로 그 사진이로군요

+ Recent posts