*Heightmap

- texture를 읽어와 texture의 크기 만큼 지형의 크기를 잡아주고

해당 픽셀의 음영값을 vertex의 높낮이로 정해준해준다.

 

*D3DCreateTextureFromFileEx()

- Heightmap texture를 LPDIRECT3DTEXTURE9 com객체에 메모리를 할당하여 texture 정보를 읽어온다.

 

*D3DSURFACE_DESC 구조체

- LPDIRECT3DTEXTURE9의 GetLevelDesc() 함수를 이용하여

D3DSURFACE_DESC구조체에 texture정보를 추출한다.

- texture의 width와 height는 2^n의 수로 변환되며

본래 texture의 크기가 2^n보다 클경우 log_2( size ) = k, 2^(k+1)로 변환한다.

 

*D3DLOCKED_RECT 구조체

- texture에 lock을 걸어 pixel정보에 접근할 수 있게 한다.

- .pBits : pixel정보를 가지고있는 포인터로 첫 주소를 가리킨다.

- .Pitch : 한 열의 길이

 

*의사 코드

LPDIRECT3DTEXTURE9 pTex = NULL;

 

D3DCreateTextureFromFileEx( pDevice, pszPath, D3DX_DEFAULT, D3DX_DEFAULT, D3DX_DEFAULT, 0

, D3DFMT_X8R8G8B8, D3DPOOL_MANAGED, D3DX_DEFAULT, D3DX_DEFAULT, 0, NULL, NULL, &pTex );

 

D3DSURFACE_DESC ddsd;

pTex->GetLevelDesc( 0, &ddsd );

POINT ptSize;

 

ptSize.x = ddsd.Width;

ptSize.y = ddsd.Height;

 

D3DLOCKED_RECT ddlr;

pTex->LockRect( 0, &ddlr, NULL, D3DLOCK_READONLY );

 

DWORD dwRowPixelSize = ddlr.Pitch / 4;

 

//반복문을 사용하여 픽셀의 포인터를 갱신한다.

for( int iZ = 0; iZ < ptSize.z; ++iZ )

{

for( int iX = 0; iX < ptSize.x; ++iX )

{

//해당 픽셀의 주소 계산

DWORD dwPixel = *( (LPDWORD)ddlr.pBits + iX + iZ * dwRowPixelSize );

 

//필요정보는 픽셀의 색상이 아니라 음영값이므로

//0x000000ff와 비트& 연산을 하여 한 byte값(blue value)을 구한다.

float fHeight = (float)( dwPixel & 0x000000ff );

}

}

 

pTex->UnlockRect( 0 );

 

pTex->Release();

 

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

picking  (0) 2024.07.26
directx terrain 약 2주간 업데이트 사항  (0) 2024.07.26
dirextx xFile 띄우기  (0) 2024.07.26
directx 지형 알파 멀티텍스쳐의 복수 사용  (0) 2024.07.26
directx 지형 알파 텍스쳐 입히기  (0) 2024.07.26
Posted by mainep
:

picking

programming/direct3d 2024. 7. 26. 10:23 |

 

 

우선 winProcedure 콜백함수에서 마우스 좌료를 얻는다

또는 API함수인 GetCursorPos함수로 window상 좌표를 받아오고

ScreenToClient함수를 사용해 Client좌표로 변형 시켜줄 수 있다.

전자는 client영역에 마우스포인터가 존재해야 좌표를 갱신하고

후자는 window상의 좌표를 변형시켜준거라 client영역을 벗어나도 좌표가 갱신된다.

 

-

 

받아온 client상의 좌표를 direct3d좌표계로 변형시켜줘야한다. 범위[ -1, 1 ]

direct3D는 왼손 좌표계를 사용한다.

 

여기서 y값을 보면 client는 좌상단을 원점으로 아래로 내려갈수록 y값이 증가하게된다.

때문에 상,하를 반전시켜주어야 한다.

 

convPos.x = 2.f * clientPos.x / backBufferWidth - 1.f

convPos.y = 1.f - 2.f * clientPos.y / backBufferHeight

convPos.z = 1.f

 

좌표계 변환도 해주었으니 이제 뷰 공간으로 변형시켜줘야한다.

IDirect3DDevice9::GetTransform() 함수를 이용하여 projection행렬을 얻어온다.

convPos.x /= matProj._11

convPos.y /= matProj._22

 

이는 d3d좌표계로 변환된 정점에 projection행렬의 역행렬을 곱해준것과 같다.

 

-

 

IDirect3DDevice9::GetTransform() 함수를 이용하여 view행렬을 얻어온다.

D3DXMatrixInverse() 함수를 이용하여 view의 역행렬을 구하면

현재 카메라의 회전행렬과 카메라의 위치를 구할수있다.

 

-

 

먼저 카메라의 위치에서 월드 공간상 마우스포인터의 위치로 향하는 방향백터를 구하기위해

D3DXVec3TransformNomal() 함수를 이용하여 matInverseView행렬을 곱해준다.

이 함수는 3차원벡터를 1x4행렬로 변환후 w원소에 0을 넣어 행렬x행렬 연산을 해준다.

이로서 월드공간상의 vPickDir을 구할 수 있다.

 

-

 

matInverseView행렬의 (4,1), (4,2), (4,3) 원소는 camera의 현재 위치를 나타낸다.

 

가공해 얻어낸 정보

- vPickDir

- vCameraPos

 

*IntersectTriangle() 분석

http://jebi.tistory.com/377

IntersectTriangle 분석

A. 기본 원리 i) 두 벡터로 만들 수 있는 삼각형 OAB가 있다. ii) 이 삼각형의 두 벡터 OA와 OB는 스칼라 u와 v에 의해 다음과 같은 벡터를 얻을 수 있다. Oa = u * OA Ob = v * OB iii) OA와 OB 사이를 지내는 벡터 OP가 있다고 하자. iv) 이 벡터 OP는 두 벡터 Oa와 Ob의 합으로 나타낼 수 있다 OP = u*OA + u*OB u와 v의 합이 1보다 작거나 같은 경우 u가 1이고, v가 0인 경우 u와 v가 각각 0.5인 경우 u가 0이고, v가 1..

jebi.tistory.com

 

 

 

Posted by mainep
:

애니메이션을 띄우고 그간 많은 시간이 지난거 같다. 

추가사항이나 변경사항의 갯수로 따지면 얼마 되지 않지만

프레임을 높히기 위해 intersect함수를 전부 갈아업었고

로딩된 하나의 스킨드 메쉬를 이용해 필요한 오브젝트의 정보만 따로 담아

하나의 스킨드메쉬로 여러개의 오브젝트를 출력할수 있게 만들었고

지형의 높이에따라 오브젝트의 높이를 업데이트 하게 만들었다.

그리고 지정된 방식에 따라 해당 애니메이션이 나오도록 만들었다 .

 

몇가지 안되지만 헤메고 돌아오느라 시간이 늦어진듯하다. 

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

높이맵 ( Heightmap )  (0) 2024.07.26
picking  (0) 2024.07.26
dirextx xFile 띄우기  (0) 2024.07.26
directx 지형 알파 멀티텍스쳐의 복수 사용  (0) 2024.07.26
directx 지형 알파 텍스쳐 입히기  (0) 2024.07.26
Posted by mainep
:

xFile을 로드하여 뷰포트상에 뿌려주려면

orig메쉬와 변환된 행렬을 곱해주어야한다.

하지만 이러한 작업을 소프트웨어적으로 하게되면 성능적 문제가 있기에

하드웨어적으로 처리할수 있도록 버텍스 쉐이더를 사용해야한다.

 

xFile로드는 이전에 한번 실패한 경험이 있어

건드리기 두려웠지만 이전보다는 생각하는 힘이 발전했나보다.

많은 시간을 투자하긴 하였지만

스킨을 가지는 케릭터 부분과

스킨이 없는 아이템부분까지 띄우는걸 완성하였다.

다음에는 에니메이션을 컨트롤 해볼까한다.

Posted by mainep
:

 

스쳐는 정말 쉽지 않은 부분인것 같다 ㅜㅜ 뙇

 

리스트박스와 텍스쳐미리보기

그리고 제일 중요한 여러장의 멀티텍스쳐의 사용

그중 하나 쉽게 풀린게 없는듯하다.

 

정말 스스로 프로그래밍을 즐기지 못하면

못할짓이라는걸 작업하는 내내 다시한번 깨닿게 되었다.

정말 다행인것같다.

 

프로그래머가 아니라

그래픽 모델러를 목표로

향해가는듯한 이 기분은 뭘까 ㅋㅋ

 

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

directx terrain 약 2주간 업데이트 사항  (0) 2024.07.26
dirextx xFile 띄우기  (0) 2024.07.26
directx 지형 알파 텍스쳐 입히기  (0) 2024.07.26
directx 지형 수정사항  (0) 2024.07.26
directx 지형 추가사항  (0) 2024.07.26
Posted by mainep
:

 

생각보다 시간이 오래걸렸다.

대충 알파값 넣으면 쉽게 될줄알았는데

여러장의 텍스쳐가 합쳐지는 SetTextureStageState에 있는 연산자를 이해해야한다.

 

프로젝트가 점점 산으로서의 구색을 갖추어

두덕리 온라인으로 진화중인것 같다.

 

다음 목표는 다수의 알파 텍스쳐를 사용하고

그것을 저장하고 로딩하는것이다 .

 

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

dirextx xFile 띄우기  (0) 2024.07.26
directx 지형 알파 멀티텍스쳐의 복수 사용  (0) 2024.07.26
directx 지형 수정사항  (0) 2024.07.26
directx 지형 추가사항  (0) 2024.07.26
다이렉트x 3d 지형 - 맵툴  (0) 2024.07.26
Posted by mainep
:

 

for( DWORD i = 0; i < m_rCheckIBZ ; i++ )
{
if( intersect ) break;
for( DWORD k = 0; k < m_rCheckIBX ; k++)
{
if( intersect ) break;
long tempVB = rSNum + (((m_rIndexSizeZ) ) * i) + ( k * 3 ) - m_fixedRPoint;
static DWORD ibNum = 0;
if( tempVB < 0 ) { continue ; }
else if( tempVB >= ((long)m_rIndexTotalSize)-3 ) { break ; }
else { ibNum = tempVB ;}
if( IntersectTriangle( m_pickOrig, m_pickDir,
m_pReferVB[m_pReferIB[ibNum]], m_pReferVB[m_pReferIB[ibNum+1]], m_pReferVB[m_pReferIB[ibNum+2]],
&scale[0], &scale[1], &scale[2] ) )
{
m_pickPos = m_pickOrig + ( m_pickDir * scale[0] );
D3DXVECTOR2 transV(0.0f, 0.0f);
DWORD transX = 0, transZ = 0 ;
transV.x = m_pickPos.x / 8.0f * m_intervalRate + m_checkX ;
transV.y = m_pickPos.z / 8.0f * m_intervalRate - m_checkZ ;
transX = (DWORD)( ( transV.x < 0 ) ? transV.x * -1.0f : transV.x );
transZ = (DWORD)( ( transV.y < 0 ) ? transV.y * -1.0f : transV.y );
sNum = transX + transZ * m_vbSizeX ;


m_pLineVB->Lock( 0, 0, (void**)&pVertices, 0 ) ;
pVertices[0].v = m_pickPos ;
pVertices[1].v = D3DXVECTOR3( m_pickPos.x, m_maxminY, m_pickPos.z ) ;
m_pLineVB->Unlock() ;
rSNum = ( ibNum%2 == 0 ) ? ibNum : ibNum - 3 ;
intersect = TRUE ;
break;
}
}
}

 

 

최적화를위해 일반 메모리의 픽킹에서

실제 좌표를 이용해 해당 VB의 번호를 직접 구해냄

 

일반메모리의 참조 범위를

횡렬 리딩에서 범위 리딩으로 수정함

 

Posted by mainep
:

 

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

 

기반인 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
: