//////////////////////////////////////////////////////////////////////////// // // Crytek Engine Source File. // Copyright (C), Crytek Studios, 2002. // ------------------------------------------------------------------------- // File name: terrain_hmap.cpp // Version: v1.00 // Created: 28/5/2001 by Vladimir Kajalin // Compilers: Visual Studio.NET // Description: highmap // ------------------------------------------------------------------------- // History: // //////////////////////////////////////////////////////////////////////////// #include "stdafx.h" float CHighMap::GetZApr(float x1, float y1) { float dDownLandZ; if( x1<1 || y1<1 || x1>=CTerrain::GetTerrainSize() || y1>=CTerrain::GetTerrainSize() ) dDownLandZ = BOTTOM_LEVEL; else { // convert into hmap space x1 /= CTerrain::GetHeightMapUnitSize(); y1 /= CTerrain::GetHeightMapUnitSize(); int nX = fastftol_positive(x1); int nY = fastftol_positive(y1); float dx1 = x1 - nX; float dy1 = y1 - nY; float dDownLandZ0 = (1.f-dx1) * (m_arrusHightMapData[nX ][nY ] & (~INFO_BITS_MASK)) + ( dx1) * (m_arrusHightMapData[nX+1][nY ] & (~INFO_BITS_MASK)); float dDownLandZ1 = (1.f-dx1) * (m_arrusHightMapData[nX ][nY+1] & (~INFO_BITS_MASK)) + ( dx1) * (m_arrusHightMapData[nX+1][nY+1] & (~INFO_BITS_MASK)); dDownLandZ = (1-dy1) * dDownLandZ0 + ( dy1) * dDownLandZ1; dDownLandZ *= TERRAIN_Z_RATIO; if(dDownLandZ < BOTTOM_LEVEL) dDownLandZ = BOTTOM_LEVEL; } return dDownLandZ; } #if defined(WIN32) && defined (_CPU_X86) inline int fastround_positive(float f) // note: only positive numbers works correct { int i; __asm fld [f] __asm fistp [i] return i; } #else inline int fastround_positive(float f) { int i; i=(int)(f+0.5f); return i; } // note: only positive numbers works correct #endif bool CHighMap::IntersectWithSector(Vec3d vStartPoint, Vec3d vStopPoint, float fDist, int nMaxTestsToScip) { // convert into hmap space float fInvUnitSize = CTerrain::GetInvUnitSize(); vStopPoint.x *= fInvUnitSize; vStopPoint.y *= fInvUnitSize; vStopPoint.z *= INV_TERRAIN_Z_RATIO; vStartPoint.x *= fInvUnitSize; vStartPoint.y *= fInvUnitSize; vStartPoint.z *= INV_TERRAIN_Z_RATIO; // scan hmap in sector Vec3d vDir = (vStopPoint - vStartPoint); int nSteps = fastftol_positive(fDist/(CTerrain::GetHeightMapUnitSize()*4)); // every 4 units //int nSteps = int(vDir.Length()/CTerrain::GetHeightMapUnitSize()/8); switch(Cry3DEngineBase::m_pCVars->e_terrain_occlusion_culling) { case 4: // far objects are culled less precise but with far hills as well (same culling speed) if(nSteps>50) nSteps=50; vDir /= (float)nSteps; break; default: // far hills are not culling vDir /= (float)nSteps; if(nSteps>50) nSteps=50; break; } Vec3d vPos = vStartPoint; vPos.z+=(INFO_BITS_MASK); int nTest=0; for(nTest=0; nTestCTerrain::GetTerrainSize() || _vPoint.y>CTerrain::GetTerrainSize() ) return false; if( vCamPos.x<0 || vCamPos.y<0 || vCamPos.x>CTerrain::GetTerrainSize() || vCamPos.y>CTerrain::GetTerrainSize() ) return false; return IntersectWithSector(vCamPos, _vPoint, fDist, nMaxTestsToScip); } #ifdef WIN64 #pragma warning( push ) //AMD Port #pragma warning( disable : 4267 ) #endif bool CHighMap::LoadHighMap(const char* file_name, ICryPak * pCryPak) { // Terrain Land dimensions = file dimensions + 1 int nArraySize = (CTerrain::GetTerrainSize()/CTerrain::GetHeightMapUnitSize())*(CTerrain::GetTerrainSize()/CTerrain::GetHeightMapUnitSize()); unsigned short * pTmpBuff = new unsigned short[nArraySize]; if(!pTmpBuff) return 0; FILE * f = pCryPak->FOpen(file_name, "rb"); if(!f) return 0; int nBytesReaded = pCryPak->FRead(pTmpBuff, sizeof(pTmpBuff[0]), (CTerrain::GetTerrainSize()/CTerrain::GetHeightMapUnitSize())*(CTerrain::GetTerrainSize()/CTerrain::GetHeightMapUnitSize()), f); if(nBytesReaded != nArraySize) { pCryPak->FClose(f); return 0; } pCryPak->FClose(f); m_arrusHightMapData.Allocate(CTerrain::GetTerrainSize()/CTerrain::GetHeightMapUnitSize()+1); int nHolesCount=0; int nLightCount=0; int nDarkCount=0; for (int t = 1; t < CTerrain::GetTerrainSize()/CTerrain::GetHeightMapUnitSize(); t++) for (int s = 1; s < CTerrain::GetTerrainSize()/CTerrain::GetHeightMapUnitSize(); s++) { m_arrusHightMapData[t][s] = pTmpBuff[(t)*(CTerrain::GetTerrainSize()/CTerrain::GetHeightMapUnitSize())+(s)]; if((m_arrusHightMapData[t][s] & STYPE_BIT_MASK) == STYPE_HOLE) nHolesCount++; if(m_arrusHightMapData[t][s] & LIGHT_BIT_MASK) nLightCount++; else nDarkCount++; m_arrusHightMapData[t][s] &= ~EXPLO_BIT_MASK; // reset explo state } delete [] pTmpBuff; m_bHightMapModified = false; return f!=0; } #ifdef WIN64 #pragma warning( pop ) //AMD Port #endif bool CHighMap::GetHoleSafe(const int & x, const int & y) { if(x>=0 && y>=0 && x>HMAP_BIT_SHIFT][(y+1)>>HMAP_BIT_SHIFT] & STYPE_BIT_MASK) == STYPE_HOLE; return false; } float CHighMap::GetZSafe(int x, int y) { if(x>=0 && y>=0 && x BOTTOM_LEVEL) return GetZ(x,y); return BOTTOM_LEVEL; } float CHighMap::GetZSafe(float x, float y) { if(x>=0 && y>=0 && x BOTTOM_LEVEL) return GetZ((int)x,(int)y); return BOTTOM_LEVEL; } /* float CHighMap::GetZ(const int x, const int y) { return TERRAIN_Z_RATIO*(m_arrusHightMapData[x>>HMAP_BIT_SHIFT][y>>HMAP_BIT_SHIFT] & (~INFO_BITS_MASK)); } */ float CHighMap::GetZF(const float x, const float y) { return TERRAIN_Z_RATIO*(m_arrusHightMapData[int(x)>>HMAP_BIT_SHIFT][int(y)>>HMAP_BIT_SHIFT] & (~INFO_BITS_MASK)); } bool CHighMap::IsOnTheLight(const int x, const int y) { if(x>=0 && y>=0 && x>HMAP_BIT_SHIFT][(y+1)>>HMAP_BIT_SHIFT] & LIGHT_BIT_MASK)!=0; return true; } uchar CHighMap::GetSurfaceTypeID(int x, int y) { if(x>=0 && y>=0 && x>HMAP_BIT_SHIFT][y>>HMAP_BIT_SHIFT] & STYPE_BIT_MASK; return 0; } int CHighMap::GetSurfaceType(int x, int y) { assert(CTerrain::GetHeightMapUnitSize()==2); if(x>0 && y>0 && x>HMAP_BIT_SHIFT][y>>HMAP_BIT_SHIFT] & STYPE_BIT_MASK) == STYPE_HOLE) return -1; // there is hole here return m_arrusHightMapData[x>>HMAP_BIT_SHIFT][y>>HMAP_BIT_SHIFT] & STYPE_BIT_MASK; } return -1; // out of the map } void CHighMap::SetLightValue(const int x, const int y, bool bValue) { if(bValue) m_arrusHightMapData[(x+1)>>HMAP_BIT_SHIFT][(y+1)>>HMAP_BIT_SHIFT] |= LIGHT_BIT_MASK; else m_arrusHightMapData[(x+1)>>HMAP_BIT_SHIFT][(y+1)>>HMAP_BIT_SHIFT] &= ~LIGHT_BIT_MASK; } void CHighMap::SetBurnedOut(int x, int y, bool bBurnedOut) { if(bBurnedOut) m_arrusHightMapData[(x+1)>>HMAP_BIT_SHIFT][(y+1)>>HMAP_BIT_SHIFT] |= EXPLO_BIT_MASK; else m_arrusHightMapData[(x+1)>>HMAP_BIT_SHIFT][(y+1)>>HMAP_BIT_SHIFT] &= ~EXPLO_BIT_MASK; } bool CHighMap::IsBurnedOut(int x, int y) { if(x>=0 && y>=0 && x>HMAP_BIT_SHIFT][(y+HMAP_BIT_SHIFT)>>HMAP_BIT_SHIFT]) != 0; return 0; }