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(); } }
|