bool TerrainLattice::Copy_Rect_to_HeightField( TTerrain* pHeightField, float x, float y, float fRadius, bool bNormalize ) { Terrain *pTerrain = GetTerrainAtPoint(x, y); if(pTerrain==NULL || pTerrain->IsEmpty()) return false; float fVertexSpacing = pTerrain->GetVertexSpacing(); int nCount = Math::Round(fRadius/fVertexSpacing)*2+1; float fMinX = x-nCount/2*fVertexSpacing; float fMinY = y-nCount/2*fVertexSpacing; pHeightField->CreatePlane(nCount, 0,fVertexSpacing); for(int i=0;i<nCount;i++) { for(int j=0;j<nCount;j++) { float fVertexX = fMinX + i*fVertexSpacing; float fVertexY = fMinY + j*fVertexSpacing; float fElev = GetVertexElevation(fVertexX, fVertexY); pHeightField->SetHeight(i,j, fElev); } } if(bNormalize) pHeightField->Normalize(); return true; }
bool TerrainLattice::Apply_HeightField_to_Rect( TTerrain* pHeightField, float x, float y, bool bRecalculateGeometry, bool bRecoverHeightData) { Terrain *pTerrain = GetTerrainAtPoint(x, y); if(pTerrain==NULL || pTerrain->IsEmpty()) return false; float fVertexSpacing = pTerrain->GetVertexSpacing(); int nCount = pHeightField->GetGridSize(); float fMinX = x-nCount/2*fVertexSpacing; float fMinY = y-nCount/2*fVertexSpacing; if(bRecoverHeightData) pHeightField->Recover(); for(int i=0;i<nCount;i++) { for(int j=0;j<nCount;j++) { float fVertexX = fMinX + i*fVertexSpacing; float fVertexY = fMinY + j*fVertexSpacing; SetVertexElevation(fVertexX, fVertexY, pHeightField->GetHeight(i,j), false); } } if(bRecalculateGeometry == true) { /** make the region slightly larger. the exact region radius is (nCount-1)*fVertexSpacing/2 */ RecalculateTerrainGeometry(x,y,nCount*fVertexSpacing/2); } return true; }
void TerrainLattice::MergeHeightField( float x, float y, const char* filename, int mergeOperation/*=0*/, float weight1/*=1.0*/, float weight2/*=1.0*/, int nSmoothPixels/*=7*/ ) { // snap to terrain grid. if(SnapPointToVertexGrid(x,y) == false) return; CTerrainFilters terrafilter; TTerrain* pHeightField = terrafilter.GetTerrainData(); Terrain *pTerrain = GetTerrainAtPoint(x, y); if(pTerrain==NULL || pTerrain->IsEmpty()) return; float fVertexSpacing = pTerrain->GetVertexSpacing(); if(pHeightField->CreatePlane(filename, fVertexSpacing)) { // Set the height to the lowest terrain height in the inner radius terrafilter.SetConstEdgeHeight(0, nSmoothPixels); CTerrainFilters terrafilter2; TTerrain* pHeightFieldCurrent = terrafilter2.GetTerrainData(); if(Copy_Rect_to_HeightField(pHeightFieldCurrent, x,y, (pHeightField->GetGridSize()-1)*fVertexSpacing/2,false) == false) return; terrafilter2.Merge( pHeightFieldCurrent, pHeightField, weight1, weight2, (CTerrainFilters::MergeOperation)mergeOperation); if(Apply_HeightField_to_Rect(pHeightFieldCurrent, x,y,true,true) == false) return; } }
void TerrainLattice::SetVertexElevation(float x, float y, float newElevation, bool recalculate_geometry) { /* some vertex on border needs to be duplicated. This macro set the vertex on the given terrain tile. * it is just to make the code easy to understand */ #define SETELEVATION(indexX, indexY) \ pTerrain = GetTerrain((indexX), (indexY));\ if(pTerrain && (!pTerrain->IsEmpty())){\ int nIndex = pTerrain->GetVertexW(x,y);\ pTerrain->SetVertexElevation(nIndex, newElevation,recalculate_geometry);\ pTerrain->SetModified(true, MODIFIED_HEIGHTMAP);\ } Terrain *pTerrain = NULL; if(x<0 || y<0) return; int indexX = (int)(x / m_TerrainWidth); int indexY = (int)(y / m_TerrainHeight); SETELEVATION(indexX, indexY); float dX = x-indexX*m_TerrainWidth; float dY = y-indexY*m_TerrainHeight; float fRadius = pTerrain->GetVertexSpacing()/2; if(dX<fRadius) { SETELEVATION(indexX-1, indexY); if(dY<fRadius) { SETELEVATION(indexX-1, indexY-1); } else if(dY>m_TerrainHeight-fRadius) { SETELEVATION(indexX-1, indexY+1); } } else if(dX>m_TerrainWidth-fRadius) { SETELEVATION(indexX+1, indexY); if(dY<fRadius) { SETELEVATION(indexX+1, indexY-1); } else if(dY>m_TerrainHeight-fRadius) { SETELEVATION(indexX+1, indexY+1); } } if(dY<fRadius) { SETELEVATION(indexX, indexY-1); } else if(dY>m_TerrainHeight-fRadius) { SETELEVATION(indexX, indexY+1); } }
bool TerrainLattice::SnapPointToVertexGrid(float& x, float& y) { Terrain *pTerrain = GetTerrainAtPoint(x, y); if(pTerrain==NULL || pTerrain->IsEmpty()) return false; float fVertexSpacing = pTerrain->GetVertexSpacing(); x = (Math::Round(x / fVertexSpacing))*fVertexSpacing; y = (Math::Round(y / fVertexSpacing))*fVertexSpacing; return true; }
void TerrainLattice::SetVertexInfo(float x,float y,uint32 data,uint32 bitMask,uint32 bitOffset) { #define SETDATA(idxX,idxY)\ pTerrain = GetTerrain((idxX),(idxY));\ if(pTerrain && (!pTerrain->IsEmpty())){\ int idx = pTerrain->GetVertexW(x,y);\ pTerrain->SetVertexInfo(idx,data,bitMask,bitOffset);\ } Terrain* pTerrain = NULL; if(x<0 || y<0) return; int idxX = (int)(x / m_TerrainWidth); int idxY = (int)(y / m_TerrainHeight); SETDATA(idxX,idxY); float dx = x - idxX * m_TerrainWidth; float dy = y - idxY * m_TerrainHeight; float radius = pTerrain->GetVertexSpacing() / 2; if(dx < radius) { SETDATA(idxX - 1,idxY); if(dy < radius) { SETDATA(idxX-1,idxY-1); } else if(dy > m_TerrainHeight - radius) { SETDATA(idxX-1,idxY+1); } } else if(dx > m_TerrainWidth - radius) { SETDATA(idxX+1, idxY); if(dy<radius) { SETDATA(idxX+1, idxY-1); } else if(dy>m_TerrainHeight-radius) { SETDATA(idxX+1, idxY+1); } } if(dy<radius) { SETDATA(idxX, idxY-1); } else if(dy>m_TerrainHeight-radius) { SETDATA(idxX, idxY+1); } }
void TerrainLattice::SetTerrainInfo(float x,float y,float radius,uint32 data,uint32 bitMask,uint32 bitOffset) { if(SnapPointToVertexGrid(x,y) == false) return; Terrain* pTerrain = GetTerrainAtPoint(x,y); if(pTerrain == NULL || pTerrain->IsEmpty()) return; float vertexSpacing = pTerrain->GetVertexSpacing(); float minX = x - radius; float minY = y - radius; int count = (int)(radius * 2.f / vertexSpacing); if(count < 1) count = 1; for(int i=0;i<count;i++) { for(int j=0;j<count;j++) { float curX = minX + i * vertexSpacing; float curY = minY + j* vertexSpacing; SetVertexInfo(curX,curY,data,bitMask,bitOffset); } } Terrain* affectedTerrainTiles[4]; affectedTerrainTiles[0] = GetTerrainAtPoint(x+radius, y+radius); affectedTerrainTiles[1] = GetTerrainAtPoint(x+radius, y-radius); affectedTerrainTiles[2] = GetTerrainAtPoint(x-radius, y+radius); affectedTerrainTiles[3] = GetTerrainAtPoint(x-radius, y-radius); for(int i=0;i<4; i++) { Terrain * pTerrain = affectedTerrainTiles[i]; bool bDraw = true; for(int k=i-1;k>=0; --k) { if(affectedTerrainTiles[k] == pTerrain) { bDraw = false; break; } } if(bDraw && pTerrain != NULL && (!pTerrain->IsEmpty())) { pTerrain->RefreshTerrainInfo(); } } }