#include "StdAfx.h" #include "../PRTerrainLib/StdAfx.h" #include "../eterLib/ResourceManager.h" #include "../eterlib/StateManager.h" #include "../EterPack/EterPackManager.h" #include "AreaTerrain.h" #include "MapOutdoor.h" CDynamicPool CTerrain::ms_kPool; void CTerrain::DestroySystem() { ms_kPool.Destroy(); } CTerrain* CTerrain::New() { return ms_kPool.Alloc(); } void CTerrain::Delete(CTerrain* pkTerrain) { pkTerrain->Clear(); ms_kPool.Free(pkTerrain); } CTerrain::CTerrain() { memset(&m_lpAlphaTexture, 0, sizeof(m_lpAlphaTexture)); memset(&m_lpMarkedTexture, 0, sizeof(m_lpMarkedTexture)); Initialize(); } CTerrain::~CTerrain() { DeallocateMarkedSplats(); RAW_DeallocateSplats(); Clear(); } void CTerrain::SetMapOutDoor(CMapOutdoor * pOwnerOutdoorMap) { m_pOwnerOutdoorMap=pOwnerOutdoorMap; } void CTerrain::Clear() { DeallocateMarkedSplats(); CTerrainImpl::Clear(); Initialize(); } bool CTerrain::Initialize() { SetReady(false); m_strName = ""; m_wX = m_wY = 0xFFFF; m_bReady = false; m_bMarked = false; for (BYTE byY = 0; byY < PATCH_YCOUNT; ++byY) for (BYTE byX = 0; byX < PATCH_XCOUNT; ++byX) m_TerrainPatchList[byY * PATCH_XCOUNT + byX].Clear(); return true; } void CTerrain::LoadMiniMapTexture(const char * c_pchMiniMapFileName) { DWORD dwStart = ELTimer_GetMSec(); CGraphicImage * pImage = (CGraphicImage *) CResourceManager::Instance().GetResourcePointer(c_pchMiniMapFileName); m_MiniMapGraphicImageInstance.SetImagePointer(pImage); if (!m_MiniMapGraphicImageInstance.GetTexturePointer()->IsEmpty()) { m_lpMiniMapTexture = m_MiniMapGraphicImageInstance.GetTexturePointer()->GetD3DTexture(); Tracef("CTerrain::LoadMiniMapTexture %d ms\n", ELTimer_GetMSec() - dwStart); } else { Tracef(" CTerrain::LoadMiniMapTexture - MiniMapTexture Error"); m_lpMiniMapTexture = NULL; } } void CTerrain::LoadShadowTexture(const char * ShadowFileName) { DWORD dwStart = ELTimer_GetMSec(); CGraphicImage * pImage = (CGraphicImage *) CResourceManager::Instance().GetResourcePointer(ShadowFileName); m_ShadowGraphicImageInstance.SetImagePointer(pImage); if (!m_ShadowGraphicImageInstance.GetTexturePointer()->IsEmpty()) m_lpShadowTexture = m_ShadowGraphicImageInstance.GetTexturePointer()->GetD3DTexture(); else { TraceError(" CTerrain::LoadShadowTexture - ShadowTexture is Empty"); m_lpShadowTexture = NULL; } Tracef("CTerrain::LoadShadowTexture %d ms\n", ELTimer_GetMSec() - dwStart); } bool CTerrain::LoadShadowMap(const char * c_pszFileName) { DWORD dwStart = ELTimer_GetMSec(); Tracef("LoadShadowMap %s ", c_pszFileName); CMappedFile file; LPCVOID c_pvData; if (!CEterPackManager::Instance().Get(file, c_pszFileName, &c_pvData)) { TraceError(" CTerrain::LoadShadowMap - %s OPEN ERROR", c_pszFileName); return false; } DWORD dwShadowMapSize = sizeof(WORD) * 256 * 256; if (file.Size() != dwShadowMapSize) { TraceError(" CTerrain::LoadShadowMap - %s SIZE ERROR", c_pszFileName); return false; } memcpy(m_awShadowMap, c_pvData, dwShadowMapSize); Tracef("%d ms\n", ELTimer_GetMSec() - dwStart); return true; } ////////////////////////////////////////////////////////////////////////// // Seamless¿ë »õ·Î¿î ÇÔ¼öµé... ////////////////////////////////////////////////////////////////////////// void CTerrain::CopySettingFromGlobalSetting() { m_lViewRadius = m_pOwnerOutdoorMap->GetViewRadius(); m_fHeightScale = m_pOwnerOutdoorMap->GetHeightScale(); } WORD CTerrain::WE_GetHeightMapValue(short sX, short sY) { if (sX>=-1 && sY>=-1 && sXGetTerrainNumFromCoord(m_wX, m_wY, &byTerrainNum) ) { Tracef("CTerrain::WE_GetHeightMapValue : Can't Get TerrainNum from Coord %d, %d", m_wX, m_wY); byTerrainNum = 4; } short sTerrainCouuntX, sTerrainCouuntY; m_pOwnerOutdoorMap->GetTerrainCount(&sTerrainCouuntX, &sTerrainCouuntY); CTerrain * pTerrain = NULL; if (sY < -1) { if (m_wY <= 0) { if ( sX < -1) { if (m_wX <= 0) return GetHeightMapValue(-1, -1); else { if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum - 1, &pTerrain)) return GetHeightMapValue(-1, -1); else return pTerrain->GetHeightMapValue(sX + XSIZE, -1); } } else if (sX >= HEIGHTMAP_RAW_XSIZE - 1) { if (m_wX >= sTerrainCouuntX - 1) return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, -1); else { if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum + 1, &pTerrain)) return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, -1); else return pTerrain->GetHeightMapValue(sX - XSIZE, -1); } } else return GetHeightMapValue(sX, -1); } else { if (sX < -1) { if (m_wX <= 0) { if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum - 3, &pTerrain)) return GetHeightMapValue(-1, -1); else return pTerrain->GetHeightMapValue(-1, sY + YSIZE); } else { if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum - 4, &pTerrain)) return GetHeightMapValue(-1, -1); else return pTerrain->GetHeightMapValue(sX + XSIZE, sY + YSIZE); } } else if (sX >= HEIGHTMAP_RAW_XSIZE - 1) { if (m_wX >= sTerrainCouuntX) { if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum - 3, &pTerrain)) return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, -1); else return pTerrain->GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, sY + YSIZE); } else { if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum - 2, &pTerrain)) return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, -1); else return pTerrain->GetHeightMapValue(sX - XSIZE, sY + YSIZE); } } else { if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum - 3, &pTerrain)) return GetHeightMapValue(sX, -1); else return pTerrain->GetHeightMapValue(sX, sY + YSIZE); } } } else if (sY >= HEIGHTMAP_RAW_YSIZE - 1) { if (m_wY >= sTerrainCouuntY - 1) { if (sX < -1) { if (m_wX <= 0) return GetHeightMapValue(-1, HEIGHTMAP_RAW_XSIZE - 1); else { if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum - 1, &pTerrain)) return GetHeightMapValue(-1, HEIGHTMAP_RAW_XSIZE - 1); else return pTerrain->GetHeightMapValue(sX + XSIZE, HEIGHTMAP_RAW_YSIZE - 1); } } else if (sX >= HEIGHTMAP_RAW_XSIZE - 1) { if (m_wX >= sTerrainCouuntX - 1) return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, HEIGHTMAP_RAW_YSIZE - 1); else { if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum + 1, &pTerrain)) return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, HEIGHTMAP_RAW_YSIZE - 1); else return pTerrain->GetHeightMapValue(sX - XSIZE, HEIGHTMAP_RAW_YSIZE - 1); } } else return GetHeightMapValue(sX, HEIGHTMAP_RAW_YSIZE - 1); } else { if (sX < -1) { if (m_wX <= 0) { if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum + 3, &pTerrain)) return GetHeightMapValue(-1, HEIGHTMAP_RAW_YSIZE - 1); else return pTerrain->GetHeightMapValue(-1, sY - YSIZE); } else { if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum + 2, &pTerrain)) return GetHeightMapValue(-1, HEIGHTMAP_RAW_XSIZE - 1); else return pTerrain->GetHeightMapValue(sX + XSIZE, sY - YSIZE); } } else if (sX >= HEIGHTMAP_RAW_XSIZE - 1) { if (m_wX >= sTerrainCouuntX - 1) { if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum + 3, &pTerrain)) return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, HEIGHTMAP_RAW_YSIZE - 1); else return pTerrain->GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, sY - YSIZE); } else { if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum + 4, &pTerrain)) return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, HEIGHTMAP_RAW_YSIZE - 1); else return pTerrain->GetHeightMapValue(sX - XSIZE, sY - YSIZE); } } else { if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum + 3, &pTerrain)) return GetHeightMapValue(sX, HEIGHTMAP_RAW_YSIZE - 1); else return pTerrain->GetHeightMapValue(sX, sY - YSIZE); } } } else { if (sX < -1) { if (m_wX <= 0) return GetHeightMapValue(-1, sY); else { if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum - 1, &pTerrain)) return GetHeightMapValue(-1, sY); else return pTerrain->GetHeightMapValue(sX + XSIZE, sY); } } else if (sX >= HEIGHTMAP_RAW_XSIZE - 1) { if (m_wX >= sTerrainCouuntX - 1) return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, sY); else { if (!m_pOwnerOutdoorMap->GetTerrainPointer(byTerrainNum + 1, &pTerrain)) return GetHeightMapValue(HEIGHTMAP_RAW_XSIZE - 1, sY); else return pTerrain->GetHeightMapValue(sX - XSIZE, sY); } } else return GetHeightMapValue(sX, sY); } } bool CTerrain::GetNormal(int ix, int iy, D3DXVECTOR3 * pv3Normal) { long lMapWidth = XSIZE * CELLSCALE; long lMapHeight = YSIZE * CELLSCALE; while (ix < 0) ix += lMapWidth; while (iy < 0) iy += lMapHeight; while (ix > lMapWidth) ix -= lMapWidth; while (iy > lMapHeight) iy -= lMapHeight; ix /= CELLSCALE; iy /= CELLSCALE; D3DXVECTOR3 v3Noraml; char * n = (char*) &m_acNormalMap[(iy * NORMALMAP_XSIZE + ix)*3]; pv3Normal->x = -((float)*n++) * 0.007874016f; pv3Normal->y = ((float)*n++) * 0.007874016f; pv3Normal->z = ((float)*n++) * 0.007874016f; return true; } // Returns the height of the terrain at the given world coordinate float CTerrain::GetHeight(int x, int y) { //if (0 == CELLSCALE) //return 0.0f; x -= m_wX * XSIZE * CELLSCALE; y -= m_wY * YSIZE * CELLSCALE; if (x < 0 || y < 0 || x > XSIZE * CELLSCALE || y > XSIZE * CELLSCALE) return 0.0f; long xdist; /* x mod size of tile */ long ydist; /* y mod size of tile */ float xslope, yslope; /* slopes of heights between vertices */ float h1, h2, h3; long x2, y2; float ooscale; /* Find out the distance relative to the top left vertex of a tile */ xdist = x % CELLSCALE; ydist = y % CELLSCALE; /* Convert into pixel coordinates */ ooscale = 1.0f / ((float)CELLSCALE); x /= CELLSCALE; y /= CELLSCALE; x2 = x; y2 = y; /* Get the height and color of the pixel at the top left corner */ h1 = (float) GetHeightMapValue(x2, y2) * m_fHeightScale; /* Get the height and color of the pixel at the bottom right corner */ x2 = x + 1; y2 = y + 1; h2 = (float) GetHeightMapValue(x2, y2) * m_fHeightScale; /* Left triangle */ if (xdist <= ydist) { x2 = x; y2 = y + 1; h3 = (float) GetHeightMapValue(x2, y2) * m_fHeightScale; /* Get the height of the pixel at the bottom left corner */ xslope = (h2 - h3) * ooscale; yslope = (h3 - h1) * ooscale; return (h1 + (xdist * xslope + ydist * yslope)); } /* Right triangle */ x2 = x + 1; y2 = y; h3 = (float) GetHeightMapValue(x2, y2) * m_fHeightScale; /* Get the height of the pixel at the top right corner */ xslope = (h3 - h1) * ooscale; yslope = (h2 - h3) * ooscale; return (h1 + (xdist * xslope + ydist * yslope)); } ////////////////////////////////////////////////////////////////////////// // HeightMapCoord -> TileMapCoord void CTerrain::CalculateNormal(long x, long y) { D3DXVECTOR3 normal; normal.x = -m_fHeightScale * ((float)GetHeightMapValue((x-1),y)-(float)GetHeightMapValue((x+1),y)); normal.y = -m_fHeightScale * ((float)GetHeightMapValue(x,(y-1))-(float)GetHeightMapValue(x,(y+1))); normal.z = 2.0f * CELLSCALE; normal *= 127.0f / D3DXVec3Length(&normal); int ix, iy, iz; PR_FLOAT_TO_INT(normal.x, ix); PR_FLOAT_TO_INT(normal.y, iy); PR_FLOAT_TO_INT(normal.z, iz); char * n = (char*) &m_acNormalMap[(y * NORMALMAP_XSIZE + x)*3]; *n++ = (char) ix; *n++ = (char) iy; *n++ = (char) iz; } bool CTerrain::RAW_LoadTileMap(const char * c_pszFileName, bool bBGLoading) { CTerrainImpl::RAW_LoadTileMap(c_pszFileName); DWORD dwStart = ELTimer_GetMSec(); RAW_AllocateSplats(bBGLoading); Tracef("CTerrain::RAW_AllocateSplats %d\n", ELTimer_GetMSec() - dwStart); return true; } bool CTerrain::LoadHeightMap(const char * c_pszFileName) { CTerrainImpl::LoadHeightMap(c_pszFileName); DWORD dwStart = ELTimer_GetMSec(); for (WORD y = 0; y < NORMALMAP_YSIZE; ++y) for (WORD x = 0; x < NORMALMAP_XSIZE; ++x) CalculateNormal(x, y); Tracef("LoadHeightMap::CalculateNormal %d ms\n", ELTimer_GetMSec() - dwStart); return true; } bool CTerrain::LoadAttrMap(const char *c_pszFileName) { return CTerrainImpl::LoadAttrMap(c_pszFileName); } bool CTerrain::isAttrOn(WORD wCoordX, WORD wCoordY, BYTE byAttrFlag) { if (wCoordX >= ATTRMAP_XSIZE || wCoordY >= ATTRMAP_YSIZE) { Tracef("CTerrain::isAttrOn Coordiante Error! Return false... Input Coord - X : %d, Y : %d ( Limit X : %d, Y : %d)", wCoordX, wCoordY, ATTRMAP_XSIZE, ATTRMAP_YSIZE); return false; } BYTE byMapAttr = m_abyAttrMap[wCoordY * ATTRMAP_XSIZE + wCoordX]; if ( byAttrFlag < 16 ) return (byMapAttr & byAttrFlag) ? true : false; else { if ( byAttrFlag/16 == byMapAttr/16) return true; else return false; } } BYTE CTerrain::GetAttr(WORD wCoordX, WORD wCoordY) { if (wCoordX >= ATTRMAP_XSIZE || wCoordY >= ATTRMAP_YSIZE) { Tracef("CTerrain::GetAttr Coordiante Error! Return 0... Input Coord - X : %d, Y : %d ( Limit X : %d, Y : %d)", wCoordX, wCoordY, ATTRMAP_XSIZE, ATTRMAP_YSIZE); return 0; } return m_abyAttrMap[wCoordY * ATTRMAP_XSIZE + wCoordX]; } void CTerrain::GetWaterHeight(BYTE byWaterNum, long * plWaterHeight) { if (byWaterNum > m_byNumWater) { Tracef("CTerrain::GetWaterHeight WaterNum %d(Total Num %d) ERROR!", byWaterNum, m_byNumWater); return; } *plWaterHeight = m_lWaterHeight[byWaterNum]; } bool CTerrain::GetWaterHeight(WORD wCoordX, WORD wCoordY, long * plWaterHeight) { BYTE byWaterNum = *(m_abyWaterMap + (wCoordY * WATERMAP_XSIZE) + wCoordX); if (byWaterNum > m_byNumWater) { Tracef("CTerrain::GetWaterHeight (X %d, Y %d) ERROR!", wCoordX, wCoordY, m_byNumWater); return false; } *plWaterHeight = m_lWaterHeight[byWaterNum] / 2; return true; } void CTerrain::RAW_DeallocateSplats(bool bBGLoading) { for (DWORD i = 1; i < GetTextureSet()->GetTextureCount(); ++i) { TTerainSplat & rSplat = m_TerrainSplatPatch.Splats[i]; if (m_lpAlphaTexture[i]) { ULONG ulRef; do { ulRef = m_lpAlphaTexture[i]->Release(); } while(ulRef > 0); } rSplat.pd3dTexture = m_lpAlphaTexture[i] = NULL; } memset(&m_TerrainSplatPatch, 0, sizeof(m_TerrainSplatPatch)); } void CTerrain::RAW_AllocateSplats(bool bBGLoading) { RAW_DeallocateSplats(bBGLoading); DWORD dwTexCount = GetTextureSet()->GetTextureCount(); m_TerrainSplatPatch.m_bNeedsUpdate = true; for (DWORD t = 0; t < dwTexCount; ++t) m_TerrainSplatPatch.Splats[t].NeedsUpdate = 1; RAW_CountTiles(); // if ( WAIT_OBJECT_0 == LockDataWrite() ) RAW_GenerateSplat(bBGLoading); // UnlockDataWrite(); m_TerrainSplatPatch.m_bNeedsUpdate = false; } void CTerrain::RAW_CountTiles() { for (long y = 0; y < TILEMAP_RAW_YSIZE; ++y) { long lPatchIndexY = min(max((y-1)/PATCH_TILE_YSIZE,0), PATCH_YCOUNT - 1); for (long x = 0; x < TILEMAP_RAW_XSIZE; ++x) { long lPatchIndexX = min(max((x-1)/(PATCH_TILE_XSIZE), 0), PATCH_XCOUNT - 1); BYTE tilenum = m_abyTileMap[y * TILEMAP_RAW_XSIZE + x]; ++m_TerrainSplatPatch.PatchTileCount[lPatchIndexY * PATCH_XCOUNT + lPatchIndexX][tilenum]; if ( 0 == y % PATCH_TILE_YSIZE && 0 != y && (TILEMAP_RAW_YSIZE - 2) != y) { ++m_TerrainSplatPatch.PatchTileCount[min(PATCH_YCOUNT - 1, lPatchIndexY + 1) * PATCH_XCOUNT + lPatchIndexX][tilenum]; if ( 0 == x % PATCH_TILE_XSIZE && 0 != x && (TILEMAP_RAW_XSIZE - 2) != x) { ++m_TerrainSplatPatch.PatchTileCount[lPatchIndexY * PATCH_XCOUNT + min(PATCH_XCOUNT - 1, lPatchIndexX + 1)][tilenum]; ++m_TerrainSplatPatch.PatchTileCount[min(PATCH_YCOUNT - 1, lPatchIndexY + 1) * PATCH_XCOUNT + min(PATCH_XCOUNT - 1, lPatchIndexX + 1)][tilenum]; } else if ( 1 == x % PATCH_TILE_XSIZE && (TILEMAP_RAW_XSIZE -1) != x && 1 != x) { ++m_TerrainSplatPatch.PatchTileCount[lPatchIndexY * PATCH_XCOUNT + max(0, lPatchIndexX - 1)][tilenum]; ++m_TerrainSplatPatch.PatchTileCount[min(PATCH_YCOUNT - 1, lPatchIndexY + 1) * PATCH_XCOUNT + max(0, lPatchIndexX - 1)][tilenum]; } } else if ( 1 == y % PATCH_TILE_YSIZE && (TILEMAP_RAW_YSIZE -1) != y && 1 != y) { ++m_TerrainSplatPatch.PatchTileCount[max(0, lPatchIndexY - 1) * PATCH_XCOUNT + lPatchIndexX][tilenum]; if ( 0 == x % PATCH_TILE_XSIZE && 0 != x && (TILEMAP_RAW_XSIZE - 2) != x) { ++m_TerrainSplatPatch.PatchTileCount[lPatchIndexY * PATCH_XCOUNT + min(PATCH_XCOUNT - 1, lPatchIndexX + 1)][tilenum]; ++m_TerrainSplatPatch.PatchTileCount[max(0, lPatchIndexY - 1) * PATCH_XCOUNT + min(PATCH_XCOUNT - 1, lPatchIndexX + 1)][tilenum]; } else if ( 1 == x % PATCH_TILE_XSIZE && (TILEMAP_RAW_XSIZE -1) != x && 1 != x) { ++m_TerrainSplatPatch.PatchTileCount[lPatchIndexY * PATCH_XCOUNT + max(0, lPatchIndexX - 1)][tilenum]; ++m_TerrainSplatPatch.PatchTileCount[max(0, lPatchIndexY - 1) * PATCH_XCOUNT + max(0, lPatchIndexX - 1)][tilenum]; } } else { if ( 0 == x % PATCH_TILE_XSIZE && 0 != x && (TILEMAP_RAW_XSIZE - 2) != x) ++m_TerrainSplatPatch.PatchTileCount[lPatchIndexY * PATCH_XCOUNT + min(PATCH_XCOUNT - 1, lPatchIndexX + 1)][tilenum]; else if ( 1 == x % PATCH_TILE_XSIZE && (TILEMAP_RAW_XSIZE -1) != x && 1 != x) ++m_TerrainSplatPatch.PatchTileCount[lPatchIndexY * PATCH_XCOUNT + max(0, lPatchIndexX - 1)][tilenum]; } ++m_TerrainSplatPatch.TileCount[tilenum]; } } } void CTerrain::RAW_GenerateSplat(bool bBGLoading) { if (!m_TerrainSplatPatch.m_bNeedsUpdate) return; m_TerrainSplatPatch.m_bNeedsUpdate = false; BYTE abyAlphaMap[SPLATALPHA_RAW_XSIZE * SPLATALPHA_RAW_YSIZE]; BYTE * aptr; for (DWORD i = 1; i < GetTextureSet()->GetTextureCount(); ++i) { TTerainSplat & rSplat = m_TerrainSplatPatch.Splats[i]; if (rSplat.NeedsUpdate) { if (m_TerrainSplatPatch.TileCount[i] > 0) { if (rSplat.Active) // We already have an alpha map which needs to be updated { if (m_lpAlphaTexture[i]) { ULONG ulRef; do { ulRef = m_lpAlphaTexture[i]->Release(); if (ulRef > 0) TraceError(" CTerrain::RAW_GenerateSplat - TileCount > 0 : Alpha Texture Release(%d) ERROR", ulRef); } while(ulRef > 0); } rSplat.pd3dTexture = m_lpAlphaTexture[i] = NULL; } rSplat.Active = 1; rSplat.NeedsUpdate = 0; aptr = abyAlphaMap; for (long y = 0; y < SPLATALPHA_RAW_YSIZE; ++y) { for (long x = 0; x < SPLATALPHA_RAW_XSIZE; ++x) { long lTileMapOffset = y * TILEMAP_RAW_XSIZE + x; BYTE byTileNum = m_abyTileMap[lTileMapOffset]; if (byTileNum == i) *aptr = 0xFF; else if (byTileNum > i) { BYTE byTileTL, byTileTR, byTileBL, byTileBR, byTileT, byTileB, byTileL, byTileR; if ( x > 0 && y > 0 ) byTileTL = m_abyTileMap[lTileMapOffset - TILEMAP_RAW_YSIZE - 1]; else byTileTL = 0; if ( x < (SPLATALPHA_RAW_XSIZE - 1) && y > 0 ) byTileTR = m_abyTileMap[lTileMapOffset - TILEMAP_RAW_YSIZE + 1]; else byTileTR = 0; if ( x > 0 && y < (SPLATALPHA_RAW_YSIZE - 1) ) byTileBL = m_abyTileMap[lTileMapOffset + TILEMAP_RAW_YSIZE - 1]; else byTileBL = 0; if ( x < (SPLATALPHA_RAW_XSIZE - 1) && y < (SPLATALPHA_RAW_YSIZE - 1) ) byTileBR = m_abyTileMap[lTileMapOffset + TILEMAP_RAW_YSIZE + 1]; else byTileBR = 0; if ( y > 0 ) byTileT = m_abyTileMap[lTileMapOffset - TILEMAP_RAW_YSIZE]; else byTileT = 0; if ( y < (SPLATALPHA_RAW_YSIZE - 1) ) byTileB = m_abyTileMap[lTileMapOffset + TILEMAP_RAW_YSIZE]; else byTileB = 0; if ( x > 0 ) byTileL = m_abyTileMap[lTileMapOffset - 1]; else byTileL = 0; if ( x < (SPLATALPHA_RAW_XSIZE - 1) ) byTileR = m_abyTileMap[lTileMapOffset + 1]; else byTileR = 0; if (byTileTL == i || byTileTR == i || byTileBL == i || byTileBR == i || byTileT == i || byTileB == i || byTileL == i || byTileR == i) *aptr = 0xFF; else *aptr = 0x00; } else *aptr = 0x00; ++aptr; } } rSplat.pd3dTexture = AddTexture32(i, abyAlphaMap, SPLATALPHA_RAW_XSIZE, SPLATALPHA_RAW_YSIZE); } else { if (rSplat.Active) { if (m_lpAlphaTexture[i]) { ULONG ulRef; do { ulRef = m_lpAlphaTexture[i]->Release(); if (ulRef > 0) TraceError(" CTerrain::RAW_GenerateSplat - TileDount 0 : Alpha Texture Release(%d) ERROR", ulRef); } while(ulRef > 0); } rSplat.pd3dTexture = m_lpAlphaTexture[i] = NULL; } rSplat.NeedsUpdate = 0; rSplat.Active = 0; } } } } LPDIRECT3DTEXTURE8 CTerrain::AddTexture32(BYTE byImageNum, BYTE * pbyImage, long lTextureWidth, long lTextureHeight) { assert(NULL==m_lpAlphaTexture[byImageNum]); if (m_lpAlphaTexture[byImageNum]) m_lpAlphaTexture[byImageNum]->Release(); m_lpAlphaTexture[byImageNum]=NULL; HRESULT hr; D3DFORMAT format; if(ms_bSupportDXT) format = D3DFMT_A8R8G8B8; else format = D3DFMT_A4R4G4B4; bool bResizedAndSuccess = false; IDirect3DTexture8* pkTex=NULL; UINT uiNewWidth = 256; UINT uiNewHeight = 256; hr = ms_lpd3dDevice->CreateTexture( uiNewWidth, uiNewHeight, 5, 0, format, D3DPOOL_MANAGED, &pkTex); if (FAILED(hr)) { TraceError("CTerrain::AddTexture32 - CreateTexture Error"); return NULL; } BYTE abResizeImage[256*256]; { BYTE* pbDstPixel=abResizeImage; BYTE* pbSrcPixel; BYTE* abCurLine=pbyImage; for (UINT y=0; y<256; ++y, abCurLine+=258) { for (UINT x=0; x<256; ++x) { pbSrcPixel=abCurLine+x; *pbDstPixel++= ((( pbSrcPixel[0]+pbSrcPixel[1]+pbSrcPixel[2]+ pbSrcPixel[258]+pbSrcPixel[260]+ pbSrcPixel[258*2]+pbSrcPixel[258*2+1]+pbSrcPixel[258*2+2]) >>3)+pbSrcPixel[259])>>1; } } D3DLOCKED_RECT d3dlr; hr = pkTex->LockRect(0, &d3dlr, 0, 0); if (FAILED(hr)) { pkTex->Release(); return NULL; } if(ms_bSupportDXT) PutImage32(abResizeImage, (BYTE*) d3dlr.pBits, 256, d3dlr.Pitch, 256, 256, bResizedAndSuccess); else PutImage16(abResizeImage, (BYTE*) d3dlr.pBits, 256, d3dlr.Pitch, 256, 256, bResizedAndSuccess); pkTex->UnlockRect(0); } BYTE abResizeImage2[128*128]; BYTE* pbSrcBuffer=abResizeImage; BYTE* pbDstBuffer=abResizeImage2; UINT uSrcSize=256; for (UINT uMipMapLevel=1; uMipMapLevel!=pkTex->GetLevelCount(); ++uMipMapLevel) { UINT uDstSize=uSrcSize>>1; BYTE* pbDstPixel=pbDstBuffer; BYTE* pbSrcPixel; BYTE* abCurLine=pbSrcBuffer; for (UINT y=0; y!=uSrcSize; y+=2, abCurLine+=uSrcSize*2) { for (UINT x=0; x!=uSrcSize; x+=2) { pbSrcPixel=abCurLine+x; *pbDstPixel++=(pbSrcPixel[0]+pbSrcPixel[1]+pbSrcPixel[uSrcSize+0]+pbSrcPixel[uSrcSize+1])>>2; } } D3DLOCKED_RECT d3dlr; hr = pkTex->LockRect(uMipMapLevel, &d3dlr, 0, 0); if (FAILED(hr)) continue; if(ms_bSupportDXT) PutImage32(pbDstBuffer, (BYTE*) d3dlr.pBits, uDstSize, d3dlr.Pitch, uDstSize, uDstSize, bResizedAndSuccess); else PutImage16(pbDstBuffer, (BYTE*) d3dlr.pBits, uDstSize, d3dlr.Pitch, uDstSize, uDstSize, bResizedAndSuccess); hr = pkTex->UnlockRect(uMipMapLevel); std::swap(pbSrcBuffer, pbDstBuffer); uSrcSize=uDstSize; } m_lpAlphaTexture[byImageNum]=pkTex; return pkTex; } void CTerrain::PutImage32(BYTE *src, BYTE *dst, long src_pitch, long dst_pitch, long texturewidth, long textureheight, bool bResize) { for (int y = 0; y < textureheight; ++y) { for (int x = 0; x < texturewidth; ++x) { DWORD packed_pixel = src[x] << 24; *((DWORD*)(dst+x*4)) = packed_pixel; } dst += dst_pitch; src += src_pitch; } } void CTerrain::PutImage16(BYTE *src, BYTE *dst, long src_pitch, long dst_pitch, long texturewidth, long textureheight, bool bResize) { for (int y = 0; y < textureheight; ++y) { for (int x = 0; x < texturewidth; ++x) { WORD packed_pixel = src[x] << 8; //& ¿¬»ê ÇѹøÀÌ ¾Æ±õ´Ù //WORD packed_pixel = (src[x]&0xF0) << 8; *((WORD*)(dst+x*2)) = packed_pixel; } dst += dst_pitch; src += src_pitch; } } void CTerrain::SetCoordinate(WORD wCoordX, WORD wCoordY) { m_wX = wCoordX; m_wY = wCoordY; } void CTerrain::CalculateTerrainPatch() { for (BYTE byPatchNumY = 0; byPatchNumY < PATCH_YCOUNT; ++byPatchNumY) for (BYTE byPatchNumX = 0; byPatchNumX < PATCH_XCOUNT; ++byPatchNumX) _CalculateTerrainPatch(byPatchNumX, byPatchNumY); } CTerrainPatch * CTerrain::GetTerrainPatchPtr(BYTE byPatchNumX, BYTE byPatchNumY) { if (byPatchNumX < 0 || byPatchNumX >= PATCH_XCOUNT || byPatchNumY < 0 || byPatchNumY >= PATCH_YCOUNT) return NULL; return &m_TerrainPatchList[byPatchNumY * PATCH_XCOUNT + byPatchNumX]; } void CTerrain::_CalculateTerrainPatch(BYTE byPatchNumX, BYTE byPatchNumY) { if (!m_awRawHeightMap || !m_acNormalMap || !m_abyWaterMap) return; DWORD dwPatchNum = byPatchNumY * PATCH_XCOUNT + byPatchNumX; CTerrainPatch& rkTerrainPatch=m_TerrainPatchList[dwPatchNum]; if (!rkTerrainPatch.NeedUpdate()) return; const float fOpaqueWaterDepth = m_pOwnerOutdoorMap->GetOpaqueWaterDepth(); const float fOOOpaqueWaterDepth = 1.0f/fOpaqueWaterDepth; const float fTransparentWaterDepth = 0.8f * fOpaqueWaterDepth; rkTerrainPatch.Clear(); HardwareTransformPatch_SSourceVertex akSrcTerrainVertex[CTerrainPatch::TERRAIN_VERTEX_COUNT]; SWaterVertex akSrcWaterVertex[PATCH_XSIZE * PATCH_YSIZE * 6]; DWORD dwNormalWidth = CTerrainImpl::NORMALMAP_XSIZE * 3; DWORD dwStartX = byPatchNumX * PATCH_XSIZE; DWORD dwStartY = byPatchNumY * PATCH_YSIZE; WORD * wOrigRawHeightPtr = m_awRawHeightMap + ((dwStartY+1) * HEIGHTMAP_RAW_XSIZE) + dwStartX+1; char * chOrigNormalPtr = m_acNormalMap + (dwStartY * dwNormalWidth) + dwStartX * 3; BYTE * byOrigWaterPtr = m_abyWaterMap + (dwStartY * WATERMAP_XSIZE) + dwStartX; float fX, fY, fOrigX, fOrigY; fOrigX = fX = (float)(m_wX * XSIZE * CELLSCALE) + (float)(dwStartX * CELLSCALE); fOrigY = fY = (float)(m_wY * YSIZE * CELLSCALE) + (float)(dwStartY * CELLSCALE); rkTerrainPatch.SetMinX(fX); rkTerrainPatch.SetMaxX(fX + (float)(PATCH_XSIZE*CELLSCALE)); rkTerrainPatch.SetMinY(fY); rkTerrainPatch.SetMaxY(fY + (float)(PATCH_YSIZE*CELLSCALE)); float fMinZ = 999999.0f; float fMaxZ = -999999.0f; WORD wNumPlainType = 0; WORD wNumHillType = 0; WORD wNumCliffType = 0; bool bWaterExist=false; SWaterVertex* lpWaterVertex=akSrcWaterVertex; UINT uWaterVertexCount=0; HardwareTransformPatch_SSourceVertex* lpTerrainVertex=akSrcTerrainVertex; UINT uTerrainVertexCount=0; D3DXVECTOR3 kNormal; D3DXVECTOR3 kPosition; for (DWORD dwY = dwStartY; dwY <= dwStartY + PATCH_YSIZE; ++dwY) { WORD * pwRawHeight = wOrigRawHeightPtr; char * pchNormal = chOrigNormalPtr; BYTE * pbyWater = byOrigWaterPtr; fX = fOrigX; for (DWORD dwX = dwStartX; dwX <= dwStartX + PATCH_XSIZE; ++dwX) { WORD hgt = (*pwRawHeight++); kNormal.x = -(*pchNormal++) * 0.0078740f; kNormal.y = (*pchNormal++) * 0.0078740f; kNormal.z = (*pchNormal++) * 0.0078740f; kPosition.x = +fX; kPosition.y = -fY; kPosition.z = (float)(hgt) * m_fHeightScale; lpTerrainVertex->kPosition = kPosition; lpTerrainVertex->kNormal = kNormal; if (0.5f > kNormal.z) // ¼öÆòÀ¸·Î ºÎÅÍ 30µµ ÀÌÇÏ °¢À¸·Î ±â¿ï¾îÁ® ÀÖ´Ù. Cliff typeÀ¸·Î Á¤ÀÇ ++wNumCliffType; else if (0.8660254f > kNormal.z) // ¼öÆòÀ¸·Î ºÎÅÍ 60µµ ÀÌÇÏ °¢À¸·Î ±â¿ï¾îÁ® ÀÖ´Ù. Hill typeÀ¸·Î Á¤ÀÇ ++wNumHillType; else // ±× ÀÌ»óÀº plain ŸÀÔ ++wNumPlainType; if (kPosition.z > fMaxZ) fMaxZ = kPosition.z; if (kPosition.z < fMinZ) fMinZ = kPosition.z; if (0 <= dwX && 0 <= dwY && XSIZE > dwX && YSIZE > dwY && (dwStartX + PATCH_XSIZE) != dwX && (dwStartY + PATCH_YSIZE) != dwY) { BYTE byNumWater = (*pbyWater++); if (byNumWater != 0xFF) { long lWaterHeight = m_lWaterHeight[byNumWater]; if (-1 != lWaterHeight) { float fWaterTerrainHeightDifference0 = (float)(lWaterHeight - (long)hgt); if (fWaterTerrainHeightDifference0 >= fTransparentWaterDepth) fWaterTerrainHeightDifference0 = fTransparentWaterDepth; if (fWaterTerrainHeightDifference0 <= 0.0f) fWaterTerrainHeightDifference0 = 0.0f; float fWaterTerrainHeightDifference1 = (float)(lWaterHeight - (long)(*(pwRawHeight + CTerrainImpl::HEIGHTMAP_RAW_XSIZE - 1))); if (fWaterTerrainHeightDifference1 >= fTransparentWaterDepth) fWaterTerrainHeightDifference1 = fTransparentWaterDepth; if (fWaterTerrainHeightDifference1 <= 0.0f) fWaterTerrainHeightDifference1 = 0.0f; float fWaterTerrainHeightDifference2 = (float)(lWaterHeight - (long)(*(pwRawHeight))); if (fWaterTerrainHeightDifference2 >= fTransparentWaterDepth) fWaterTerrainHeightDifference2 = fTransparentWaterDepth; if (fWaterTerrainHeightDifference2 <= 0.0f) fWaterTerrainHeightDifference2 = 0.0f; float fWaterTerrainHeightDifference3 = (float)(lWaterHeight - (long)(*(pwRawHeight + CTerrainImpl::HEIGHTMAP_RAW_XSIZE))); if (fWaterTerrainHeightDifference3 >= fTransparentWaterDepth) fWaterTerrainHeightDifference3 = fTransparentWaterDepth; if (fWaterTerrainHeightDifference3 <= 0.0f) fWaterTerrainHeightDifference3 = 0.0f; DWORD dwAlpha0; DWORD dwAlpha1; DWORD dwAlpha2; DWORD dwAlpha3; PR_FLOAT_TO_INT(fWaterTerrainHeightDifference0 * fOOOpaqueWaterDepth * 255.0f, dwAlpha0); PR_FLOAT_TO_INT(fWaterTerrainHeightDifference1 * fOOOpaqueWaterDepth * 255.0f, dwAlpha1); PR_FLOAT_TO_INT(fWaterTerrainHeightDifference2 * fOOOpaqueWaterDepth * 255.0f, dwAlpha2); PR_FLOAT_TO_INT(fWaterTerrainHeightDifference3 * fOOOpaqueWaterDepth * 255.0f, dwAlpha3); DWORD dwAlphaKey=(dwAlpha0<<24)|(dwAlpha1<<16)|(dwAlpha2<<8)|dwAlpha3; if (dwAlphaKey!=0) { assert(lpWaterVertexx = fX; lpWaterVertex->y = -fY; lpWaterVertex->z = (float)lWaterHeight * m_fHeightScale; lpWaterVertex->dwDiffuse = ((dwAlpha0 << 24) & 0xFF000000) | 0x000000FF;// 0x000F939B lpWaterVertex++; lpWaterVertex->x = fX; lpWaterVertex->y = -fY - float(CELLSCALE); lpWaterVertex->z = (float)lWaterHeight * m_fHeightScale; lpWaterVertex->dwDiffuse = ((dwAlpha1 << 24) & 0xFF000000) | 0x00FFFFFF; lpWaterVertex++; lpWaterVertex->x = fX + float(CELLSCALE); lpWaterVertex->y = -fY; lpWaterVertex->z = (float)lWaterHeight * m_fHeightScale; lpWaterVertex->dwDiffuse = ((dwAlpha2 << 24) & 0xFF000000) | 0x00FFFFFF; lpWaterVertex++; lpWaterVertex->x = fX + float(CELLSCALE); lpWaterVertex->y = -fY; lpWaterVertex->z = (float)lWaterHeight * m_fHeightScale; lpWaterVertex->dwDiffuse = ((dwAlpha2 << 24) & 0xFF000000) | 0x00FFFFFF; lpWaterVertex++; lpWaterVertex->x = fX; lpWaterVertex->y = -fY - float(CELLSCALE); lpWaterVertex->z = (float)lWaterHeight * m_fHeightScale; lpWaterVertex->dwDiffuse = ((dwAlpha1 << 24) & 0xFF000000) | 0x00FFFFFF; lpWaterVertex++; lpWaterVertex->x = fX + float(CELLSCALE); lpWaterVertex->y = -fY - float(CELLSCALE); lpWaterVertex->z = (float)lWaterHeight * m_fHeightScale; lpWaterVertex->dwDiffuse = ((dwAlpha3 << 24) & 0xFF0000FF) | 0x00FFFFFF; lpWaterVertex++; uWaterVertexCount+=6; bWaterExist = true; } } } } ++lpTerrainVertex; ++uTerrainVertexCount; fX += float(CELLSCALE); } wOrigRawHeightPtr += CTerrainImpl::HEIGHTMAP_RAW_XSIZE; chOrigNormalPtr += dwNormalWidth; byOrigWaterPtr += CTerrainImpl::XSIZE; fY += float(CELLSCALE); } if (wNumPlainType <= max(wNumHillType, wNumCliffType)) { if (wNumCliffType <= wNumHillType) rkTerrainPatch.SetType(CTerrainPatch::PATCH_TYPE_HILL); else rkTerrainPatch.SetType(CTerrainPatch::PATCH_TYPE_CLIFF); } rkTerrainPatch.SetWaterExist(bWaterExist); rkTerrainPatch.SetMinZ(fMinZ); rkTerrainPatch.SetMaxZ(fMaxZ); assert((PATCH_XSIZE+1)*(PATCH_YSIZE+1)==uTerrainVertexCount); rkTerrainPatch.BuildTerrainVertexBuffer(akSrcTerrainVertex); if (bWaterExist) rkTerrainPatch.BuildWaterVertexBuffer(akSrcWaterVertex, uWaterVertexCount); rkTerrainPatch.NeedUpdate(false); } void CTerrain::AllocateMarkedSplats(BYTE * pbyAlphaMap) { TTerainSplat & rAttrSplat = m_MarkedSplatPatch.Splats[0]; HRESULT hr; if (m_lpMarkedTexture) { ULONG ulRef; do { ulRef = m_lpMarkedTexture->Release(); } while(ulRef > 0); } do { hr = ms_lpd3dDevice->CreateTexture(ATTRMAP_XSIZE, ATTRMAP_YSIZE, 1, 0, D3DFMT_A8R8G8B8, D3DPOOL_MANAGED, &m_lpMarkedTexture); } while(FAILED(hr)); D3DLOCKED_RECT d3dlr; do { hr = m_lpMarkedTexture->LockRect(0, &d3dlr, 0, 0); } while(FAILED(hr)); PutImage32(pbyAlphaMap, (BYTE*) d3dlr.pBits, ATTRMAP_XSIZE, d3dlr.Pitch, ATTRMAP_XSIZE, ATTRMAP_YSIZE); do { hr = m_lpMarkedTexture->UnlockRect(0); } while(FAILED(hr)); rAttrSplat.pd3dTexture = m_lpMarkedTexture; m_bMarked = true; } void CTerrain::DeallocateMarkedSplats() { TTerainSplat & rSplat = m_MarkedSplatPatch.Splats[0]; if (m_lpMarkedTexture) { ULONG ulRef; do { ulRef = m_lpMarkedTexture->Release(); } while(ulRef > 0); } rSplat.pd3dTexture = NULL; m_lpMarkedTexture = NULL; m_bMarked = FALSE; memset(&m_MarkedSplatPatch, 0, sizeof(m_MarkedSplatPatch)); }