266 lines
8.2 KiB
C++
266 lines
8.2 KiB
C++
#pragma once
|
|
|
|
|
|
//#include "EnvironmentInfo.h"
|
|
|
|
|
|
class CTerrainAttributeInfoForMap
|
|
{
|
|
private:
|
|
std::string m_strAttributeFileName;
|
|
int m_nMapX;
|
|
int m_nMapY;
|
|
|
|
X2D::Point<int> *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<int> *m_pPoints = new X2D::Point<int>[nPointCount];
|
|
//static X2D::Point<int> *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<int>[nPointCount];
|
|
m_unPointArraySize = nPointCount;
|
|
}
|
|
|
|
pStream->Read( m_pPoints, sizeof( X2D::Point<int> ) * nPointCount );
|
|
//fprintf( fp, "COUNT:%d\n", nPointCount );
|
|
|
|
WORD wTile=0;
|
|
|
|
std::vector<X2D::Point<int>> 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<X2D::Polygon<int>*> 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<int> addPt = vecPoint[k]; // 가까운 두 점과 삼각형을 이룰 다른 점
|
|
X2D::Point<int> 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<int> 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<int>* poly = new X2D::Polygon<int>;
|
|
bool bValid = poly->Set(tempBuf, tempBuf + 4);
|
|
if (bValid)
|
|
{
|
|
vecMaskPolygon.push_back(poly); // 저장해둔다
|
|
}
|
|
else
|
|
{
|
|
assert( bValid && "추가 마스킹 폴리곤 생성과정에서 에러" );
|
|
delete poly;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
////////////////////////// 여기까지
|
|
|
|
X2D::Polygon<int>* pPolygon = new X2D::Polygon<int>;
|
|
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; pCnt<vecMaskPolygon.size(); pCnt++)
|
|
{
|
|
pTerrainMapEngine->AddAttributePolygon( vecMaskPolygon[pCnt] ); // 위에서 찾은 마스크 폴리곤을 추가.
|
|
}
|
|
|
|
//fprintf( fp, "\n" );
|
|
}
|
|
//fclose( fp );
|
|
|
|
delete pStream;
|
|
}
|
|
|
|
~CTerrainAttributeInfoForMap()
|
|
{
|
|
if(m_pPoints) delete[] m_pPoints;
|
|
m_pPoints = NULL;
|
|
m_unPointArraySize = 0;
|
|
}
|
|
};
|