업데이트된 맵툴은 각각의 역활을 클래스화를 하여 세분화 하였다.

 

기반인 D3DMain문을 시작으로

유틸리티로 카메라와 다이얼로그를 갖고 프로그램의 목적인 Terrain이 있다.

그곳에 드로잉을 위한 오브젝트 클래스들이 있다.

 

이번 업데이트의 핵심은

다이얼로그의 클래스화와 카메라의 추가이다.

우선 유연한 카메라를 심어줌으로인해 여러 시각에서 바라볼수있다.

 

지형을 만드는 툴이라는 프로그램을 설계중이니

다이얼로그의 클래스화로 내입맛에 맞는 방식대로 툴을 만들수있게되었다.

 

그리고 지형을 만드는 동안과 만드는 후의 사용을 위해

데이터의 저장되 로드를 추가하였다.

 

다음 추가목표는 이미지를 선택하여 지형에 텍스쳐를 입히는것이다 .

 

Posted by mainep
:

 

기본적인 vertex up & down, 다이얼로그를 사용한 증감률과 반지름 조절이 가능하다.

 

void CTERRAIN::Intersect( BOOL RBT, BOOL LBT, HWND gm_hWnd, BOOL mouseMove )
{
LPCUSTOMVERTEX pVertices, pCirVertices; //VB에 사용할 구조체 포인터
WORD *pIndices; //IB에 사용될 WORD 포인터
D3DXVECTOR3 centerPos; //삼각형을 이루는 각 한쌍의 인덱스중 좌측 상단의 vetex
BOOL intersect = FALSE; //픽킹의 성공여부
float scale[3] = {0.0f,}; //IntersectTriangle에 인자로 넘겨줄 scale배열
D3DXVECTOR3 orig, dir( 0.0f, -1.0f, 0.0f ); //원의 픽킹에 사용될 변수
static WORD realIBTotalSize = 8 * 8 * 6; //index의 총 길이
static BOOL first = TRUE; //첫 로딩의 판단
static DWORD sNum = 0; //VB의 번호
static DWORD referSNum = 0, referENum = 0; //참조메모리의 시작인덱스와 끝인덱스
static float lenthMinSize = (m_radiusSize * m_intervalRate -0.5f * m_intervalRate)*(m_radiusSize * m_intervalRate -0.5f * m_intervalRate); //원의 최소값의 제곱
static float lenthMaxSize = (m_radiusSize * m_intervalRate +0.5f * m_intervalRate)*(m_radiusSize * m_intervalRate +0.5f * m_intervalRate); //원의 최대값의 제곱
//원 리사이즈시 변수 초기화
if( m_reSize )
{
first = TRUE;
sNum = 0;
referSNum = 0, referENum = 0;
lenthMinSize = (m_radiusSize * m_intervalRate -0.5f * m_intervalRate)*(m_radiusSize * m_intervalRate -0.5f * m_intervalRate);
lenthMaxSize = (m_radiusSize * m_intervalRate +0.5f * m_intervalRate)*(m_radiusSize * m_intervalRate +0.5f * m_intervalRate);
m_reSize = FALSE;
}
//첫 로딩
if( first )
{
//가상 메모리로 픽킹된 삼각형의 좌측 상단 vertex를 구한다.
for( DWORD i = 0; i < m_rIndexTotalSize; i+=3 )
{
if( IntersectTriangle( m_pickOrig, m_pickDir,
m_pReferVB[m_pReferIB[i]], m_pReferVB[m_pReferIB[i+1]], m_pReferVB[m_pReferIB[i+2]],
&scale[0], &scale[1], &scale[2] ) )
{
m_pickPos = m_pickOrig + ( m_pickDir * scale[0] );
centerPos = m_pReferVB[m_pReferIB[(i%2 == 0) ? i+1 : i]] + D3DXVECTOR3( 1.0f, 0.0f, -1.0f);
referSNum = ((i - m_rIndexRoadSize[0])) > m_rIndexTotalSize ? 0 : (i - m_rIndexRoadSize[0]);
referENum = (referSNum + m_rIndexRoadSize[1]) > m_rIndexTotalSize ? m_rIndexTotalSize : (referSNum + m_rIndexRoadSize[1]);
first = FALSE;
}
}
//위에서 구한 centerPos로 VB의 시작 번호를 구한다.
for( short i = m_virtualVBSize / 2; i < m_vbSizeZ-m_virtualVBSize/2; i++ )
{
for( short k = m_virtualVBSize / 2; k < m_vbSizeX-m_virtualVBSize/2; k++ )
{
WORD vbNum = i * m_vbSizeX + k;
DWORD cnt = 0;
m_ppTerVB[vbNum]->Lock( 0, 0, (void**)&pVertices, 0 );
for( WORD a = 0; a < 9; a++ )
{
for( WORD b = 0; b < 9; b++)
{
D3DXVECTOR3 tempV = pVertices[cnt++].v;
tempV.y = 0.0f;
if( tempV == centerPos )
{
sNum = i * m_vbSizeX + k;
}
}
}
m_ppTerVB[vbNum]->Unlock();
}
}
}
//이후의 로딩
else if( !first )
{
for( DWORD i = referSNum; i < referENum; i+=3 )
{
if( IntersectTriangle( m_pickOrig, m_pickDir,
m_pReferVB[m_pReferIB[i]], m_pReferVB[m_pReferIB[i+1]], m_pReferVB[m_pReferIB[i+2]],
&scale[0], &scale[1], &scale[2] ) )
{
m_pickPos = m_pickOrig + ( m_pickDir * scale[0] );
centerPos = m_pReferVB[m_pReferIB[(i%2 == 0) ? i+1 : i]] + D3DXVECTOR3( 1.0f, 0.0f, -1.0f);
referSNum = ((i - m_rIndexRoadSize[0])) > m_rIndexTotalSize ? 0 : (i - m_rIndexRoadSize[0]);
referENum = (referSNum + m_rIndexRoadSize[1]) > m_rIndexTotalSize ? m_rIndexTotalSize : (referSNum + m_rIndexRoadSize[1]);
break;
}
}
DWORD cnt = 0;
m_pCirVB->Lock(0, 0, (void**)&pCirVertices, 0 );
m_pTerIB->Lock(0, 0, (void**)&pIndices, 0 );
for( short i =0; i < m_virtualVBSize; i++ )
{
for( short k = 0; k < m_virtualVBSize; k++)
{
DWORD vbNum = sNum + ((m_vbSizeX) * i) + k - m_fixedVBPoint;
m_ppTerVB[vbNum]->Lock( 0, 0, (void**)&pVertices, 0 );
if( !intersect )
{
DWORD cnt = 0;
for( WORD a = 0; a < 9; a++ )
{
for( WORD b = 0; b < 9; b++)
{
D3DXVECTOR3 tempV = pVertices[cnt++].v;
tempV.y = 0.0f;
if( tempV == centerPos )
{
sNum = vbNum;
intersect = TRUE;
}
}
}
}
if( mouseMove )
{


//가상의 원의 위치와 VB의 삼각형이 픽킹을 하지는지 구해낸후
//실제 원의 y값을 증감 시킨다.
for( WORD m = 0; m < realIBTotalSize; m+=3 )
{
D3DXVECTOR3 tempV = pVertices[pIndices[m]].v;
tempV.y = 0.0f;
float checkLen = D3DXVec3LengthSq(&(tempV - m_pickPos));
if(checkLen < lenthMaxSize && checkLen > lenthMinSize)
{
for(short b = 0; b < m_cirTic; b++)
{
pCirVertices[b].v.x = m_pReferCir[b].x + m_pickPos.x;
pCirVertices[b].v.z = m_pReferCir[b].z + m_pickPos.z;
orig = pCirVertices[b].v;
orig.y = 1000.0f;
if(IntersectTriangle( orig, dir,
pVertices[pIndices[m]].v, pVertices[pIndices[m+1]].v, pVertices[pIndices[m+2]].v,
&scale[0], &scale[1], &scale[2]))
{
cnt++;
pCirVertices[b].v.y = (orig + dir * scale[0]).y+0.1f;
}
}
}
}
}
m_ppTerVB[vbNum]->Unlock();
}
}
m_pTerIB->Unlock();
m_pCirVB->Unlock();
}
if(intersect && LBT)
{
float checkRadius = ( m_radiusSize * m_intervalRate - 1.5f ) * (m_radiusSize * m_intervalRate - 1.5f); //원의 반지름보다 조금 작은값의 제곱
float checkSELine = m_realVBSize * 8.0f * m_intervalRate / 2.0f; //실제 VB의 총 길이
//픽킹된 VB의 vertex의 y값을 증감시킨다.
for( WORD i = 0; i < m_virtualVBSize; i++ )
{
for( WORD k = 0; k < m_virtualVBSize; k++)
{
DWORD vbNum = sNum + ((m_vbSizeX) * i) + k - m_fixedVBPoint;
m_ppTerVB[vbNum]->Lock(0, 0, (void**)&pVertices, 0);
for( WORD a = 0; a < 9; a++)
{
for( WORD b = 0; b < 9; b++)
{
WORD count = 9*a+b;
D3DXVECTOR3 checkV = pVertices[count].v;
checkV.y = 0.0f;
float d = D3DXVec3LengthSq(&(checkV - m_pickPos));
float r = checkRadius;
if( d < r && checkV.x > -checkSELine && checkV.x < checkSELine && checkV.z > -checkSELine && checkV.z < checkSELine)
{
float increaseY = sinf(D3DXToRadian( 90.0f - (90.0f * d / r) ) )*(m_increaseRate);
pVertices[count].v.y += increaseY;
}
}
}
m_ppTerVB[vbNum]->Unlock();
}
}
}
//vertex 초기화
if( RBT )
{
DWORD cnt = 0;
for( WORD i = 0; i < m_vbSizeZ; i++)
{
for( WORD k = 0; k < m_vbSizeX; k++)
{
m_ppTerVB[cnt]->Lock(0, 0, (void**)&pVertices, 0);
DWORD cnt2 = 0;
for( WORD a = 0; a < 9; a++ )
{
for(WORD b = 0; b < 9; b++)
{
pVertices[cnt2++].v.y = 0.0f;
}
}
m_ppTerVB[cnt++]->Unlock();
}
}
m_pCirVB->Lock( 0, 0, (void**)&pCirVertices, 0 );
for( WORD i = 0; i < m_cirTic; i++)
{
pCirVertices[i].v.y = 0.0f;
}
m_pCirVB->Unlock();
}
}

 

 

일반 메모리를 사용하여 픽킹된곳의 실제 좌표값을 얻어내어

VB의 배열을 탐색한 후 해당 VB의 실제 번호를 알아내고

픽킹된 좌표와 탐색한 vertex의 차백터한 백터의 크기가 반지름의 제곱에 크기보다 작은

vertex들의 y값을 증가시킨다.

 

차후에 카메라 클래스를 구현하여 맵툴에 적용시킨후

다른 세부사항을 추가할 계획이다.

 

'programming > direct3d' 카테고리의 다른 글

directx 지형 알파 멀티텍스쳐의 복수 사용  (0) 2024.07.26
directx 지형 알파 텍스쳐 입히기  (0) 2024.07.26
directx 지형 수정사항  (0) 2024.07.26
directx 지형 추가사항  (0) 2024.07.26
IntersectTriangle 픽킹  (0) 2024.07.26
Posted by mainep
:

 

LPDIRECT3DDEVICE9 객체와

Proc에서 받은 마우스 위치값 MouseX, MouseY 값과

InterSectTriangle 함수에서 사용할 PickOrigV,와 PickDirV라는 구조체 일반 변수를 넘겨준다.

void GetPickVector( LPDIRECT3DDEVICE9 pd3dDevice, WORD &MouseX, WORD &MouseY, D3DXVECTOR3 *PickOrigV,D3DXVECTOR3 *PickDirV)
{
//투영 행렬을 담을 메트릭스 객체


D3DXMATRIXA16 matProj;


//현재 적용된 투영 행렬의 값을 디바이스 객체를 이용해 불러와
//matProj 메트릭스에 담아준다
pd3dDevice->GetTransform( D3DTS_PROJECTION, &matProj );
D3DXVECTOR3 v;
//화면 공간 좌표에서 카메라 공간 좌표로 변환
v.x = ( ( ( 2.0f * MouseX ) / WIDTH_RES ) - 1 ) / matProj._11;
v.y = -( ( ( 2.0f * MouseY ) / HEIGHT_RES ) - 1 ) / matProj._22;
v.z = 1.0f;


//디바이스 객체로 뷰스페이스 행렬을 받아와 역행렬을 구해준다.
D3DXMATRIXA16 matView, m;
pd3dDevice->GetTransform( D3DTS_VIEW, &matView );
D3DXMatrixInverse( &m, NULL, &matView );


//카메라 좌표로 변환된 구조체 변수에 뷰의 역행렬을 곱해서
//월드 공간 좌표로 변환시킨다.
PickDirV->x = v.x*m._11 + v.y*m._21 + v.z*m._31;
PickDirV->y = v.x*m._12 + v.y*m._22 + v.z*m._32;
PickDirV->z = v.x*m._13 + v.y*m._23 + v.z*m._33;


//광선의 시작점
PickOrigV->x = m._41;
PickOrigV->y = m._42;
PickOrigV->z = m._43;
}

 

 

GetPickVector함수에서 구한 PickOrig와 PirDir을 인자로 넘겨주고

교차판정을 위한 v0, v1, v2 버텍스를 넘겨준다.

PickOrig과 v0의 거리값 t와 v0 - v1의 비율 u, v0 - v2의 비율 v를 받을수있도록

인자로 넘겨준다.

 

마우스의 포인터와 교차가 일어나면 true값을

교차가 일어나지 않는다면 false값을 반환한다.

 

BOOL IntersectTriangle( const D3DXVECTOR3& orig,
const D3DXVECTOR3& dir, D3DXVECTOR3& v0,
D3DXVECTOR3& v1, D3DXVECTOR3& v2,
FLOAT* t, FLOAT* u, FLOAT* v )
{
// Find vectors for two edges sharing vert0
D3DXVECTOR3 edge1 = v1 - v0;
D3DXVECTOR3 edge2 = v2 - v0;
// Begin calculating determinant - also used to calculate U parameter
D3DXVECTOR3 pvec;
D3DXVec3Cross( &pvec, &dir, &edge2 );
// If determinant is near zero, ray lies in plane of triangle
FLOAT det = D3DXVec3Dot( &edge1, &pvec );
D3DXVECTOR3 tvec;
if( det > 0 )
{
tvec = orig - v0;
}
else
{
tvec = v0 - orig;
det = -det;
}
if( det < 0.0001f )
return FALSE;
// Calculate U parameter and test bounds
*u = D3DXVec3Dot( &tvec, &pvec );
if( *u < 0.0f || *u > det )
return FALSE;
// Prepare to test V parameter
D3DXVECTOR3 qvec;
D3DXVec3Cross( &qvec, &tvec, &edge1 );
// Calculate V parameter and test bounds
*v = D3DXVec3Dot( &dir, &qvec );
if( *v < 0.0f || *u + *v > det )
return FALSE;
// Calculate t, scale parameters, ray intersects triangle
*t = D3DXVec3Dot( &edge2, &qvec );
FLOAT fInvDet = 1.0f / det;
*t *= fInvDet;
*u *= fInvDet;
*v *= fInvDet;
return TRUE;
}
Posted by mainep
: