#pragma once //#include "EnvironmentInfo.h" class CTerrainAttributeInfoForMap { private: std::string m_strAttributeFileName; int m_nMapX; int m_nMapY; X2D::Point *m_pPoints; size_t m_unPointArraySize; public: bool CheckMap( int nMapX, int nMapY ) { if( nMapX != m_nMapX || nMapY != m_nMapY ) return true; return false; } public: CTerrainAttributeInfoForMap( CTerrainMapEngine *pTerrainMapEngine, const char* szAttributeFileName, int nMapX, int nMapY, bool bCreateWire ) : m_nMapX( nMapX ) , m_nMapY( nMapY ), m_pPoints( NULL ), m_unPointArraySize( 0 ) { // 파일 열기 KStream* pStream = KFileManager::Instance().CreateStreamFromResource( szAttributeFileName, true ); if( NULL == pStream ) { // assert( false && "속성 정보 파일이 없음." ); return; } const CTerrainSeamlessWorldInfo* pSeamlessWorldInfo = pTerrainMapEngine->GetSeamlessWorldInfo(); if(pSeamlessWorldInfo == NULL) { delete pStream; // assert( false && "pSeamlessWorldInfo == NULL 이네" ); return; } float fMapLen = (float)( pSeamlessWorldInfo->GetTileCountPerSegment() * pSeamlessWorldInfo->GetSegmentCountPerMap() ) * (float)pSeamlessWorldInfo->GetTileLength(); float fAttrLength = pSeamlessWorldInfo->GetTileLength() / (float)c_nAttrCountPerTile; m_strAttributeFileName = szAttributeFileName; m_nMapX = nMapX; m_nMapY = nMapY; int nPolygonCount = 0; pStream->Read( &nPolygonCount, sizeof( nPolygonCount ) ); K3DVertex v1, v2; //FILE *fp = fopen( "pl.txt", "w" ); //fprintf( fp, "TOTAL:%d\n\n", nPolygonCount ); int cnt = 0; for( int i = 0; i < nPolygonCount ; i++ ) { int nPointCount = 0; pStream->Read( &nPointCount, sizeof( nPointCount ) ); if( nPointCount < 3 ) continue; //X2D::Point *m_pPoints = new X2D::Point[nPointCount]; //static X2D::Point *m_pPoints = NULL; //static size_t m_unPointArraySize = 0; if(m_pPoints && m_unPointArraySize > (size_t)nPointCount) { // do nothing } else { if(m_pPoints) delete[] m_pPoints; m_pPoints = new X2D::Point[nPointCount]; m_unPointArraySize = nPointCount; } pStream->Read( m_pPoints, sizeof( X2D::Point ) * nPointCount ); //fprintf( fp, "COUNT:%d\n", nPointCount ); WORD wTile=0; std::vector> vecPoint; for( int j = 0; j < nPointCount; ++j ) { vecPoint.push_back(m_pPoints[j]); m_pPoints[j].x *= fAttrLength; //형 변환 하지 마셈!!! m_pPoints[j].y *= fAttrLength; //형 변환 하지 마셈!!! // * 맨날 컴파일할때마다 warning보는 다른 사람: 아악~~~ 형 변환 하고 싶어~~~~~ 이런 ambiguous한 코드를 그냥 두다니~~~~~~~~ m_pPoints[j].x += (int)( (float)nMapX * fMapLen ); m_pPoints[j].y += (int)( (float)nMapY * fMapLen ); //fprintf( fp, "%d,%d\n", m_pPoints[j].x, m_pPoints[j].y ); } std::vector*> vecMaskPolygon; /////////////////////////////// 1단위(변환전)짜리 작은 틈으로 캐릭터가 기어나가는걸 막는 마스킹 폴리곤 생성 by 정동섭 if (vecPoint.size() > 30) // 문제가 되는 폴리곤은 맵전체를 감싸는 폴리곤이 대부분이므로 너무 작은 폴리곤은 패스 { for (int j=0; j<(int)vecPoint.size(); j++) { for (int k=j+7; k<(int)vecPoint.size(); k++) { if ( j + (int)vecPoint.size() - 7 > k ) // 바로 근처 있는 점끼리는 체크하지 않는다. 최소한 두 점 사이에 6개의 다른 점이 있어야 함. (맵을 한바퀴 돌아와야 하므로) { int xDist, yDist, _xDist, _yDist; _xDist = vecPoint[j].x - vecPoint[k].x; _yDist = vecPoint[j].y - vecPoint[k].y; xDist = abs(_xDist); yDist = abs(_yDist); X2D::Point addPt = vecPoint[k]; // 가까운 두 점과 삼각형을 이룰 다른 점 X2D::Point addPt2 = vecPoint[k]; // 가까운 두 점과 삼각형을 이룰 다른 점 const int gapSize = 2; bool isClose = false; if ((xDist == 0) && (yDist <= gapSize)) // 두 점은 반드시 가로나 세로, 혹은 대각선으로 붙어있어야만 한다. { isClose = true; addPt.x++; addPt2.x--; } else if ((xDist <= gapSize) && (yDist == 0)) { isClose = true; addPt.y++; addPt2.y--; } else if ((xDist <= gapSize) && (yDist <= gapSize)) { isClose = true; addPt.x = max(vecPoint[j].x, vecPoint[k].x); addPt.y = max(vecPoint[j].y, vecPoint[k].y); addPt2.x = min(vecPoint[j].x, vecPoint[k].x); addPt2.y = min(vecPoint[j].y, vecPoint[k].y); if ((addPt == vecPoint[j]) || addPt == vecPoint[k]) addPt.y = min(vecPoint[j].y, vecPoint[k].y); if ((addPt2 == vecPoint[j]) || addPt2 == vecPoint[k]) addPt2.y = max(vecPoint[j].y, vecPoint[k].y); } if (isClose) { X2D::Point tempBuf[4]; // 삼각형을 만든다 tempBuf[0] = vecPoint[j]; tempBuf[1] = addPt; tempBuf[2] = vecPoint[k]; tempBuf[3] = addPt2; tempBuf[0].x += _xDist; // 정확히 구멍에 꼭맞는 삼각형을 만들면 뚫릴때가 있어서 tempBuf[0].y += _yDist; // 구멍보다 큰 마개를 만든다. tempBuf[2].x -= _xDist; tempBuf[2].y -= _yDist; for (int cnt=0; cnt<4; cnt++) // 맵좌표로 변환 { tempBuf[cnt].x *= fAttrLength; //형 변환 하지 마셈!!! tempBuf[cnt].y *= fAttrLength; //형 변환 하지 마셈!!! // * 맨날 컴파일할때마다 warning보는 다른 사람: 아악~~~ 형 변환 하고 싶어~~~~~ 이런 ambiguous한 코드를 그냥 두다니~~~~~~~~ tempBuf[cnt].x += (int)( (float)nMapX * fMapLen ); tempBuf[cnt].y += (int)( (float)nMapY * fMapLen ); } X2D::Polygon* poly = new X2D::Polygon; bool bValid = poly->Set(tempBuf, tempBuf + 4); if (bValid) { vecMaskPolygon.push_back(poly); // 저장해둔다 } else { assert( bValid && "추가 마스킹 폴리곤 생성과정에서 에러" ); delete poly; } } } } } } ////////////////////////// 여기까지 X2D::Polygon* pPolygon = new X2D::Polygon; bool bValidPolygon = pPolygon->Set(m_pPoints, m_pPoints + nPointCount); assert( bValidPolygon && "일부 속성 겹쳐서 날아갔음!!!" ); if(bCreateWire && bValidPolygon) { for( int j = 0; j < nPointCount; ++j ) { if(j >= 1) { v1.x = (float) m_pPoints[j - 1].x; v1.y = (float) m_pPoints[j - 1].y; pTerrainMapEngine->GetTerrainHeight(v1.x, v1.y, v1.z,wTile ); v1.z += 20.f; v2.x = (float) m_pPoints[j].x; v2.y = (float) m_pPoints[j].y; pTerrainMapEngine->GetTerrainHeight(v2.x, v2.y, v2.z,wTile ); v2.z += 20.0f; pTerrainMapEngine->AddWireAttributePolygonLine(v1, v2); } } // 마지막 라인은 수동으로 v1.x = (float) m_pPoints[nPointCount - 1].x; v1.y = (float) m_pPoints[nPointCount - 1].y; pTerrainMapEngine->GetTerrainHeight(v1.x, v1.y, v1.z,wTile); v1.z += 20.0f; v2.x = (float) m_pPoints[0].x; v2.y = (float) m_pPoints[0].y; pTerrainMapEngine->GetTerrainHeight(v2.x, v2.y, v2.z,wTile); v2.z += 20.0f; pTerrainMapEngine->AddWireAttributePolygonLine(v1, v2); } size_t s_unLimit = 500; if(m_unPointArraySize > s_unLimit) { if(m_pPoints) delete[] m_pPoints; m_pPoints = NULL; m_unPointArraySize = 0; } if( bValidPolygon ) pTerrainMapEngine->AddAttributePolygon( pPolygon ); else { assert( false && "유효하지 않는 지형 속성이 발견됨 맵팀에 문의해주세요" ); _oprint( "DELETE:%d\n", nPointCount ); delete pPolygon; } for (size_t pCnt=0; pCntAddAttributePolygon( vecMaskPolygon[pCnt] ); // 위에서 찾은 마스크 폴리곤을 추가. } //fprintf( fp, "\n" ); } //fclose( fp ); delete pStream; } ~CTerrainAttributeInfoForMap() { if(m_pPoints) delete[] m_pPoints; m_pPoints = NULL; m_unPointArraySize = 0; } };