diff options
Diffstat (limited to 'src/graphics/engine/terrain.cpp')
-rw-r--r-- | src/graphics/engine/terrain.cpp | 969 |
1 files changed, 464 insertions, 505 deletions
diff --git a/src/graphics/engine/terrain.cpp b/src/graphics/engine/terrain.cpp index 6b26281..3e70719 100644 --- a/src/graphics/engine/terrain.cpp +++ b/src/graphics/engine/terrain.cpp @@ -44,111 +44,88 @@ Gfx::CTerrain::CTerrain(CInstanceManager* iMan) m_engine = static_cast<Gfx::CEngine*>( m_iMan->SearchInstance(CLASS_ENGINE) ); m_water = static_cast<Gfx::CWater*>( m_iMan->SearchInstance(CLASS_WATER) ); - m_mosaic = 20; - m_brick = 1 << 4; - m_size = 10.0f; - m_vision = 200.0f; - m_scaleMapping = 0.01f; - m_scaleRelief = 1.0f; - m_subdivMapping = 1; - m_depth = 2; - m_levelMatMax = 0; - m_multiText = true; - m_levelText = false; - m_wind = Math::Vector(0.0f, 0.0f, 0.0f); - m_defHardness = 0.5f; - - m_levelMats.reserve(LEVEL_MAT_PREALLOCATE_COUNT); + m_mosaicCount = 20; + m_brickCount = 1 << 4; + m_brickSize = 10.0f; + m_vision = 200.0f; + m_textureScale = 0.01f; + m_scaleRelief = 1.0f; + m_textureSubdivCount = 1; + m_depth = 2; + m_maxMaterialID = 0; + m_wind = Math::Vector(0.0f, 0.0f, 0.0f); + m_defaultHardness = 0.5f; + m_useMaterials = false; + + m_materials.reserve(LEVEL_MAT_PREALLOCATE_COUNT); m_flyingLimits.reserve(FLYING_LIMIT_PREALLOCATE_COUNT); m_buildingLevels.reserve(BUILDING_LEVEL_PREALLOCATE_COUNT); + + FlushBuildingLevel(); + FlushFlyingLimit(); + FlushMaterials(); } Gfx::CTerrain::~CTerrain() { } -/** - The terrain is composed of mosaics, themselves composed of bricks. - Each brick is composed of two triangles. - mosaic: number of mosaics along the axes X and Z - brick: number of bricks (power of 2) - size: size of a brick along the axes X and Z - vision: vision before a change of resolution - scaleMapping: scale textures for mapping - -\verbatim - ^ z - | <---> brick*size - +---+---+---+---+ - | | | |_|_| mosaic = 4 - | | | | | | brick = 2 (brickP2=1) - +---+---+---+---+ - |\ \| | | | - |\ \| | | | - +---+---o---+---+---> x - | | | | | - | | | | | - +---+---+---+---+ - | | | | | The land is viewed from above here. - | | | | | - +---+---+---+---+ - <---------------> mosaic*brick*size -\endverbatim */ -bool Gfx::CTerrain::Generate(int mosaic, int brickPow2, float size, float vision, - int depth, float hardness) +bool Gfx::CTerrain::Generate(int mosaicCount, int brickCountPow2, float brickSize, + float vision, int depth, float hardness) { - m_mosaic = mosaic; - m_brick = 1 << brickPow2; - m_size = size; + m_mosaicCount = mosaicCount; + m_brickCount = 1 << brickCountPow2; + m_brickSize = brickSize; m_vision = vision; m_depth = depth; - m_defHardness = hardness; + m_defaultHardness = hardness; m_engine->SetTerrainVision(vision); - m_multiText = true; - m_levelText = false; - m_scaleMapping = 1.0f / (m_brick*m_size); - m_subdivMapping = 1; + m_textureScale = 1.0f / (m_brickCount*m_brickSize); + m_textureSubdivCount = 1; + + m_useMaterials = false; int dim = 0; - dim = (m_mosaic*m_brick+1)*(m_mosaic*m_brick+1); + dim = (m_mosaicCount*m_brickCount+1)*(m_mosaicCount*m_brickCount+1); std::vector<float>(dim).swap(m_relief); - dim = m_mosaic*m_subdivMapping*m_mosaic*m_subdivMapping; - std::vector<int>(dim).swap(m_texture); + dim = m_mosaicCount*m_textureSubdivCount*m_mosaicCount*m_textureSubdivCount; + std::vector<int>(dim).swap(m_textures); - dim = m_mosaic*m_mosaic; - std::vector<int>(dim).swap(m_objRank); + dim = m_mosaicCount*m_mosaicCount; + std::vector<int>(dim).swap(m_objRanks); return true; } -int Gfx::CTerrain::GetMosaic() +int Gfx::CTerrain::GetMosaicCount() { - return m_mosaic; + return m_mosaicCount; } -int Gfx::CTerrain::GetBrick() +int Gfx::CTerrain::GetBrickCount() { - return m_brick; + return m_brickCount; } -float Gfx::CTerrain::GetSize() +float Gfx::CTerrain::GetBrickSize() { - return m_size; + return m_brickSize; } -float Gfx::CTerrain::GetScaleRelief() +float Gfx::CTerrain::GetReliefScale() { return m_scaleRelief; } bool Gfx::CTerrain::InitTextures(const std::string& baseName, int* table, int dx, int dy) { - m_levelText = false; + m_useMaterials = false; + m_texBaseName = baseName; size_t pos = baseName.find('.'); if (pos == baseName.npos) @@ -161,69 +138,60 @@ bool Gfx::CTerrain::InitTextures(const std::string& baseName, int* table, int dx m_texBaseExt = m_texBaseName.substr(pos); } - for (int y = 0; y < m_mosaic*m_subdivMapping; y++) + for (int y = 0; y < m_mosaicCount*m_textureSubdivCount; y++) { - for (int x = 0; x < m_mosaic*m_subdivMapping; x++) + for (int x = 0; x < m_mosaicCount*m_textureSubdivCount; x++) { - m_texture[x+y*m_mosaic] = table[(x%dx)+(y%dy)*dx]; + m_textures[x+y*m_mosaicCount] = table[(x%dx)+(y%dy)*dx]; } } return true; } -void Gfx::CTerrain::LevelFlush() +void Gfx::CTerrain::FlushMaterials() { - m_levelMats.clear(); - m_levelMatMax = 0; - m_levelID = 1000; - LevelCloseTable(); + m_materials.clear(); + m_maxMaterialID = 0; + m_materialAutoID = 1000; + FlushMaterialPoints(); } -void Gfx::CTerrain::LevelMaterial(int id, std::string& baseName, float u, float v, - int up, int right, int down, int left, - float hardness) +void Gfx::CTerrain::AddMaterial(int id, const std::string& texName, const Math::Point &uv, + int up, int right, int down, int left, + float hardness) { - LevelOpenTable(); + InitMaterialPoints(); if (id == 0) - id = m_levelID++; // puts an ID internal standard + id = m_materialAutoID++; Gfx::TerrainMaterial tm; - tm.texName = baseName; + tm.texName = texName; tm.id = id; - tm.u = u; - tm.v = v; + tm.uv = uv; tm.mat[0] = up; tm.mat[1] = right; tm.mat[2] = down; tm.mat[3] = left; tm.hardness = hardness; - m_levelMats.push_back(tm); + m_materials.push_back(tm); - if (m_levelMatMax < up+1 ) m_levelMatMax = up+1; - if (m_levelMatMax < right+1) m_levelMatMax = right+1; - if (m_levelMatMax < down+1 ) m_levelMatMax = down+1; - if (m_levelMatMax < left+1 ) m_levelMatMax = left+1; + if (m_maxMaterialID < up+1 ) m_maxMaterialID = up+1; + if (m_maxMaterialID < right+1) m_maxMaterialID = right+1; + if (m_maxMaterialID < down+1 ) m_maxMaterialID = down+1; + if (m_maxMaterialID < left+1 ) m_maxMaterialID = left+1; - m_levelText = true; - m_subdivMapping = 4; + m_useMaterials = true; + m_textureSubdivCount = 4; } /** - The size of the image must be dimension dx and dy with dx=dy=(mosaic*brick)+1. - The image must be 24 bits/pixel - - Converts coordinated image (x;y) -> world (x;-;z) : - Wx = 5*Ix-400 - Wz = -(5*Iy-400) - - Converts coordinated world (x;-;z) -> image (x;y) : - Ix = (400+Wx)/5 - Iy = (400-Wz)/5 */ -bool Gfx::CTerrain::ResFromPNG(const std::string& fileName) + * The image must be 24 bits/pixel and grayscale and dx x dy in size + * with dx = dy = (mosaic*brick)+1 */ +bool Gfx::CTerrain::LoadResources(const std::string& fileName) { CImage img; if (! img.Load(CApplication::GetInstance().GetDataFilePath(m_engine->GetTextureDir(), fileName))) @@ -231,7 +199,7 @@ bool Gfx::CTerrain::ResFromPNG(const std::string& fileName) ImageData *data = img.GetData(); - int size = (m_mosaic*m_brick)+1; + int size = (m_mosaicCount*m_brickCount)+1; m_resources.clear(); @@ -241,8 +209,13 @@ bool Gfx::CTerrain::ResFromPNG(const std::string& fileName) (data->surface->format->BytesPerPixel != 3) ) return false; - // Assuming the data format is compatible - memcpy(&m_resources[0], data->surface->pixels, 3*size*size); + unsigned char* pixels = static_cast<unsigned char*>(data->surface->pixels); + int pitch = data->surface->pitch; + + for (int y = 0; y < size; y++) + { + memcpy(&m_resources[3*size*y], &pixels[pitch*y], 3*size); + } return true; } @@ -252,14 +225,14 @@ Gfx::TerrainRes Gfx::CTerrain::GetResource(const Math::Vector &p) if (m_resources.empty()) return Gfx::TR_NULL; - int x = static_cast<int>((p.x + (m_mosaic*m_brick*m_size)/2.0f)/m_size); - int y = static_cast<int>((p.z + (m_mosaic*m_brick*m_size)/2.0f)/m_size); + int x = static_cast<int>((p.x + (m_mosaicCount*m_brickCount*m_brickSize)/2.0f)/m_brickSize); + int y = static_cast<int>((p.z + (m_mosaicCount*m_brickCount*m_brickSize)/2.0f)/m_brickSize); - if ( x < 0 || x > m_mosaic*m_brick || - y < 0 || y > m_mosaic*m_brick ) + if ( x < 0 || x > m_mosaicCount*m_brickCount || + y < 0 || y > m_mosaicCount*m_brickCount ) return Gfx::TR_NULL; - int size = (m_mosaic*m_brick)+1; + int size = (m_mosaicCount*m_brickCount)+1; int resR = m_resources[3*x+3*size*(size-y-1)]; int resG = m_resources[3*x+3*size*(size-y-1)+1]; @@ -284,20 +257,10 @@ void Gfx::CTerrain::FlushRelief() } /** - The size of the image must be dimension dx and dy with dx=dy=(mosaic*brick)+1. - The image must be 24 bits/pixel, but gray scale: - white = ground (y=0) - black = mountain (y=255*scaleRelief) - - Converts coordinated image(x;y) -> world (x;-;z) : - Wx = 5*Ix-400 - Wz = -(5*Iy-400) - - Converts coordinated world (x;-;z) -> image (x;y) : - Ix = (400+Wx)/5 - Iy = (400-Wz)/5 */ -bool Gfx::CTerrain::ReliefFromPNG(const std::string &fileName, float scaleRelief, - bool adjustBorder) + * The image must be 24 bits/pixel and dx x dy in size + * with dx = dy = (mosaic*brick)+1 */ +bool Gfx::CTerrain::LoadRelief(const std::string &fileName, float scaleRelief, + bool adjustBorder) { m_scaleRelief = scaleRelief; @@ -307,20 +270,21 @@ bool Gfx::CTerrain::ReliefFromPNG(const std::string &fileName, float scaleRelief ImageData *data = img.GetData(); - int size = (m_mosaic*m_brick)+1; + int size = (m_mosaicCount*m_brickCount)+1; if ( (data->surface->w != size) || (data->surface->h != size) || (data->surface->format->BytesPerPixel != 3) ) return false; unsigned char* pixels = static_cast<unsigned char*>(data->surface->pixels); + int pitch = data->surface->pitch; float limit = 0.9f; for (int y = 0; y < size; y++) { for (int x = 0; x < size; x++) { - float level = (255 - pixels[3*x+3*size*(size-y-1)]) * scaleRelief; + float level = (255 - pixels[3*x+pitch*(size-y-1)]) * scaleRelief; float dist = Math::Max(fabs(static_cast<float>(x-size/2)), fabs(static_cast<float>(y-size/2))); @@ -340,13 +304,13 @@ bool Gfx::CTerrain::ReliefFromPNG(const std::string &fileName, float scaleRelief return true; } -bool Gfx::CTerrain::ReliefAddDot(Math::Vector pos, float scaleRelief) +bool Gfx::CTerrain::AddReliefPoint(Math::Vector pos, float scaleRelief) { - float dim = (m_mosaic*m_brick*m_size)/2.0f; - int size = (m_mosaic*m_brick)+1; + float dim = (m_mosaicCount*m_brickCount*m_brickSize)/2.0f; + int size = (m_mosaicCount*m_brickCount)+1; - pos.x = (pos.x+dim)/m_size; - pos.z = (pos.z+dim)/m_size; + pos.x = (pos.x+dim)/m_brickSize; + pos.z = (pos.z+dim)/m_brickSize; int x = static_cast<int>(pos.x); int y = static_cast<int>(pos.z); @@ -360,33 +324,20 @@ bool Gfx::CTerrain::ReliefAddDot(Math::Vector pos, float scaleRelief) return true; } -void Gfx::CTerrain::LimitPos(Math::Vector &pos) -{ -// TODO: #if _TEEN -// dim = (m_mosaic*m_brick*m_size)/2.0f*0.98f; - - float dim = (m_mosaic*m_brick*m_size)/2.0f*0.92f; - - if (pos.x < -dim) pos.x = -dim; - if (pos.x > dim) pos.x = dim; - if (pos.z < -dim) pos.z = -dim; - if (pos.z > dim) pos.z = dim; -} - void Gfx::CTerrain::AdjustRelief() { - if (m_depth == 1) return; + if (m_depth == 1) return; - int ii = m_mosaic*m_brick+1; + int ii = m_mosaicCount*m_brickCount+1; int b = 1 << (m_depth-1); - for (int y = 0; y < m_mosaic*m_brick; y += b) + for (int y = 0; y < m_mosaicCount*m_brickCount; y += b) { - for (int x = 0; x < m_mosaic*m_brick; x += b) + for (int x = 0; x < m_mosaicCount*m_brickCount; x += b) { int xx = 0; int yy = 0; - if ((y+yy)%m_brick == 0) + if ((y+yy)%m_brickCount == 0) { float level1 = m_relief[(x+0)+(y+yy)*ii]; float level2 = m_relief[(x+b)+(y+yy)*ii]; @@ -397,7 +348,7 @@ void Gfx::CTerrain::AdjustRelief() } yy = b; - if ((y+yy)%m_brick == 0) + if ((y+yy)%m_brickCount == 0) { float level1 = m_relief[(x+0)+(y+yy)*ii]; float level2 = m_relief[(x+b)+(y+yy)*ii]; @@ -408,7 +359,7 @@ void Gfx::CTerrain::AdjustRelief() } xx = 0; - if ((x+xx)%m_brick == 0) + if ((x+xx)%m_brickCount == 0) { float level1 = m_relief[(x+xx)+(y+0)*ii]; float level2 = m_relief[(x+xx)+(y+b)*ii]; @@ -419,7 +370,7 @@ void Gfx::CTerrain::AdjustRelief() } xx = b; - if ((x+xx)%m_brick == 0) + if ((x+xx)%m_brickCount == 0) { float level1 = m_relief[(x+xx)+(y+0)*ii]; float level2 = m_relief[(x+xx)+(y+b)*ii]; @@ -435,14 +386,14 @@ void Gfx::CTerrain::AdjustRelief() Math::Vector Gfx::CTerrain::GetVector(int x, int y) { Math::Vector p; - p.x = x*m_size - (m_mosaic*m_brick*m_size)/2; - p.z = y*m_size - (m_mosaic*m_brick*m_size)/2; + p.x = x*m_brickSize - (m_mosaicCount*m_brickCount*m_brickSize) / 2.0; + p.z = y*m_brickSize - (m_mosaicCount*m_brickCount*m_brickSize) / 2.0; - if ( !m_relief.empty() && - x >= 0 && x <= m_mosaic*m_brick && - y >= 0 && y <= m_mosaic*m_brick ) + if ( !m_relief.empty() && + x >= 0 && x <= m_mosaicCount*m_brickCount && + y >= 0 && y <= m_mosaicCount*m_brickCount ) { - p.y = m_relief[x+y*(m_mosaic*m_brick+1)]; + p.y = m_relief[x+y*(m_mosaicCount*m_brickCount+1)]; } else { @@ -452,7 +403,7 @@ Math::Vector Gfx::CTerrain::GetVector(int x, int y) return p; } -/** Calculates a normal soft, taking into account the six adjacent triangles: +/** Calculates an averaged normal, taking into account the six adjacent triangles: \verbatim ^ y @@ -481,16 +432,16 @@ Gfx::VertexTex2 Gfx::CTerrain::GetVertex(int x, int y, int step) Math::Vector s(0.0f, 0.0f, 0.0f); - if (x-step >= 0 && y+step <= m_mosaic*m_brick+1) + if (x-step >= 0 && y+step <= m_mosaicCount*m_brickCount+1) { s += Math::NormalToPlane(b,a,o); s += Math::NormalToPlane(c,b,o); } - if (x+step <= m_mosaic*m_brick+1 && y+step <= m_mosaic*m_brick+1) + if (x+step <= m_mosaicCount*m_brickCount+1 && y+step <= m_mosaicCount*m_brickCount+1) s += Math::NormalToPlane(d,c,o); - if (x+step <= m_mosaic*m_brick+1 && y-step >= 0) + if (x+step <= m_mosaicCount*m_brickCount+1 && y-step >= 0) { s += Math::NormalToPlane(e,d,o); s += Math::NormalToPlane(f,e,o); @@ -502,19 +453,11 @@ Gfx::VertexTex2 Gfx::CTerrain::GetVertex(int x, int y, int step) s = Normalize(s); v.normal = s; - if (m_multiText) - { - int brick = m_brick/m_subdivMapping; - Math::Vector oo = GetVector((x/brick)*brick, (y/brick)*brick); - o = GetVector(x, y); - v.texCoord.x = (o.x-oo.x)*m_scaleMapping*m_subdivMapping; - v.texCoord.y = 1.0f - (o.z-oo.z)*m_scaleMapping*m_subdivMapping; - } - else - { - v.texCoord.x = o.x*m_scaleMapping; - v.texCoord.y = o.z*m_scaleMapping; - } + int brick = m_brickCount/m_textureSubdivCount; + Math::Vector oo = GetVector((x/brick)*brick, (y/brick)*brick); + o = GetVector(x, y); + v.texCoord.x = (o.x-oo.x)*m_textureScale*m_textureSubdivCount; + v.texCoord.y = 1.0f - (o.z-oo.z)*m_textureScale*m_textureSubdivCount; return v; } @@ -539,7 +482,7 @@ bool Gfx::CTerrain::CreateMosaic(int ox, int oy, int step, int objRank, if ( step == 1 && m_engine->GetGroundSpot() ) { - int i = (ox/5) + (oy/5)*(m_mosaic/5); + int i = (ox/5) + (oy/5)*(m_mosaicCount/5); std::stringstream s; s << "shadow"; s.width(2); @@ -549,9 +492,9 @@ bool Gfx::CTerrain::CreateMosaic(int ox, int oy, int step, int objRank, texName2 = s.str(); } - int brick = m_brick/m_subdivMapping; + int brick = m_brickCount/m_textureSubdivCount; - Gfx::VertexTex2 o = GetVertex(ox*m_brick+m_brick/2, oy*m_brick+m_brick/2, step); + Gfx::VertexTex2 o = GetVertex(ox*m_brickCount+m_brickCount/2, oy*m_brickCount+m_brickCount/2, step); int total = ((brick/step)+1)*2; float pixel = 1.0f/256.0f; // 1 pixel cover (*) @@ -559,24 +502,24 @@ bool Gfx::CTerrain::CreateMosaic(int ox, int oy, int step, int objRank, Math::Point uv; - for (int my = 0; my < m_subdivMapping; my++) + for (int my = 0; my < m_textureSubdivCount; my++) { - for (int mx = 0; mx < m_subdivMapping; mx++) + for (int mx = 0; mx < m_textureSubdivCount; mx++) { - if (m_levelText) + if (m_useMaterials) { - int xx = ox*m_brick + mx*(m_brick/m_subdivMapping); - int yy = oy*m_brick + my*(m_brick/m_subdivMapping); - LevelTextureName(xx, yy, texName1, uv); + int xx = ox*m_brickCount + mx*(m_brickCount/m_textureSubdivCount); + int yy = oy*m_brickCount + my*(m_brickCount/m_textureSubdivCount); + GetTexture(xx, yy, texName1, uv); } else { - int i = (ox*m_subdivMapping+mx)+(oy*m_subdivMapping+my)*m_mosaic; + int i = (ox*m_textureSubdivCount+mx)+(oy*m_textureSubdivCount+my)*m_mosaicCount; std::stringstream s; s << m_texBaseName; s.width(3); s.fill('0'); - s << m_texture[i]; + s << m_textures[i]; s << m_texBaseExt; texName1 = s.str(); } @@ -597,36 +540,33 @@ bool Gfx::CTerrain::CreateMosaic(int ox, int oy, int step, int objRank, for (int x = 0; x <= brick; x += step) { - Gfx::VertexTex2 p1 = GetVertex(ox*m_brick+mx*brick+x, oy*m_brick+my*brick+y+0 , step); - Gfx::VertexTex2 p2 = GetVertex(ox*m_brick+mx*brick+x, oy*m_brick+my*brick+y+step, step); + Gfx::VertexTex2 p1 = GetVertex(ox*m_brickCount+mx*brick+x, oy*m_brickCount+my*brick+y+0 , step); + Gfx::VertexTex2 p2 = GetVertex(ox*m_brickCount+mx*brick+x, oy*m_brickCount+my*brick+y+step, step); p1.coord.x -= o.coord.x; p1.coord.z -= o.coord.z; p2.coord.x -= o.coord.x; p2.coord.z -= o.coord.z; - if (m_multiText) + if (x == 0) { - if (x == 0) - { - p1.texCoord.x = 0.0f+(0.5f/256.0f); - p2.texCoord.x = 0.0f+(0.5f/256.0f); - } - if (x == brick) - { - p1.texCoord.x = 1.0f-(0.5f/256.0f); - p2.texCoord.x = 1.0f-(0.5f/256.0f); - } - if (y == 0) - p1.texCoord.y = 1.0f-(0.5f/256.0f); - - if (y == brick - step) - p2.texCoord.y = 0.0f+(0.5f/256.0f); + p1.texCoord.x = 0.0f+(0.5f/256.0f); + p2.texCoord.x = 0.0f+(0.5f/256.0f); + } + if (x == brick) + { + p1.texCoord.x = 1.0f-(0.5f/256.0f); + p2.texCoord.x = 1.0f-(0.5f/256.0f); } + if (y == 0) + p1.texCoord.y = 1.0f-(0.5f/256.0f); + + if (y == brick - step) + p2.texCoord.y = 0.0f+(0.5f/256.0f); - if (m_levelText) + if (m_useMaterials) { - p1.texCoord.x /= m_subdivMapping; // 0..1 -> 0..0.25 - p1.texCoord.y /= m_subdivMapping; - p2.texCoord.x /= m_subdivMapping; - p2.texCoord.y /= m_subdivMapping; + p1.texCoord.x /= m_textureSubdivCount; // 0..1 -> 0..0.25 + p1.texCoord.y /= m_textureSubdivCount; + p2.texCoord.x /= m_textureSubdivCount; + p2.texCoord.y /= m_textureSubdivCount; if (x == 0) { @@ -635,11 +575,11 @@ bool Gfx::CTerrain::CreateMosaic(int ox, int oy, int step, int objRank, } if (x == brick) { - p1.texCoord.x = (1.0f/m_subdivMapping)-dp; - p2.texCoord.x = (1.0f/m_subdivMapping)-dp; + p1.texCoord.x = (1.0f/m_textureSubdivCount)-dp; + p2.texCoord.x = (1.0f/m_textureSubdivCount)-dp; } if (y == 0) - p1.texCoord.y = (1.0f/m_subdivMapping)-dp; + p1.texCoord.y = (1.0f/m_textureSubdivCount)-dp; if (y == brick - step) p2.texCoord.y = 0.0f+dp; @@ -650,12 +590,12 @@ bool Gfx::CTerrain::CreateMosaic(int ox, int oy, int step, int objRank, p2.texCoord.y += uv.y; } - int xx = mx*(m_brick/m_subdivMapping) + x; - int yy = my*(m_brick/m_subdivMapping) + y; - p1.texCoord2.x = (static_cast<float>(ox%5)*m_brick+xx+0.0f)/(m_brick*5); - p1.texCoord2.y = (static_cast<float>(oy%5)*m_brick+yy+0.0f)/(m_brick*5); - p2.texCoord2.x = (static_cast<float>(ox%5)*m_brick+xx+0.0f)/(m_brick*5); - p2.texCoord2.y = (static_cast<float>(oy%5)*m_brick+yy+1.0f)/(m_brick*5); + int xx = mx*(m_brickCount/m_textureSubdivCount) + x; + int yy = my*(m_brickCount/m_textureSubdivCount) + y; + p1.texCoord2.x = (static_cast<float>(ox%5)*m_brickCount+xx+0.0f)/(m_brickCount*5); + p1.texCoord2.y = (static_cast<float>(oy%5)*m_brickCount+yy+0.0f)/(m_brickCount*5); + p2.texCoord2.x = (static_cast<float>(ox%5)*m_brickCount+xx+0.0f)/(m_brickCount*5); + p2.texCoord2.y = (static_cast<float>(oy%5)*m_brickCount+yy+1.0f)/(m_brickCount*5); // Correction for 1 pixel cover // There is 1 pixel cover around each of the 16 surfaces: @@ -693,40 +633,38 @@ bool Gfx::CTerrain::CreateMosaic(int ox, int oy, int step, int objRank, return true; } -Gfx::TerrainMaterial* Gfx::CTerrain::LevelSearchMat(int id) +Gfx::TerrainMaterial* Gfx::CTerrain::FindMaterial(int id) { - for (int i = 0; i < static_cast<int>( m_levelMats.size() ); i++) + for (int i = 0; i < static_cast<int>( m_materials.size() ); i++) { - if (id == m_levelMats[i].id) - return &m_levelMats[i]; + if (id == m_materials[i].id) + return &m_materials[i]; } return nullptr; } -void Gfx::CTerrain::LevelTextureName(int x, int y, std::string& name, Math::Point &uv) +void Gfx::CTerrain::GetTexture(int x, int y, std::string& name, Math::Point &uv) { - x /= m_brick/m_subdivMapping; - y /= m_brick/m_subdivMapping; + x /= m_brickCount/m_textureSubdivCount; + y /= m_brickCount/m_textureSubdivCount; - TerrainMaterial* tm = LevelSearchMat(m_levelDots[x+y*m_levelDotSize].id); + TerrainMaterial* tm = FindMaterial(m_materialPoints[x+y*m_materialPointCount].id); if (tm == nullptr) { name = "xxx.png"; - uv.x = 0.0f; - uv.y = 0.0f; + uv = Math::Point(0.0f, 0.0f); } else { name = tm->texName; - uv.x = tm->u; - uv.y = tm->v; + uv = tm->uv; } } -float Gfx::CTerrain::LevelGetHeight(int x, int y) +float Gfx::CTerrain::GetHeight(int x, int y) { - int size = (m_mosaic*m_brick+1); + int size = (m_mosaicCount*m_brickCount+1); if (x < 0 ) x = 0; if (x >= size) x = size-1; @@ -736,15 +674,15 @@ float Gfx::CTerrain::LevelGetHeight(int x, int y) return m_relief[x+y*size]; } -bool Gfx::CTerrain::LevelGetDot(int x, int y, float min, float max, float slope) +bool Gfx::CTerrain::CheckMaterialPoint(int x, int y, float min, float max, float slope) { - float hc = LevelGetHeight(x, y); + float hc = GetHeight(x, y); float h[4] = { - LevelGetHeight(x+0, y+1), - LevelGetHeight(x+1, y+0), - LevelGetHeight(x+0, y-1), - LevelGetHeight(x-1, y+0) + GetHeight(x+0, y+1), + GetHeight(x+1, y+0), + GetHeight(x+0, y-1), + GetHeight(x-1, y+0) }; if (hc < min || hc > max) @@ -776,25 +714,22 @@ bool Gfx::CTerrain::LevelGetDot(int x, int y, float min, float max, float slope) return false; } - -/** Returns the index within m_levelMats or -1 if there is not. - m_levelMats[i].id gives the identifier. */ -int Gfx::CTerrain::LevelTestMat(char *mat) +int Gfx::CTerrain::FindMaterialByNeighbors(char *mat) { - for (int i = 0; i < static_cast<int>( m_levelMats.size() ); i++) + for (int i = 0; i < static_cast<int>( m_materials.size() ); i++) { - if ( m_levelMats[i].mat[0] == mat[0] && - m_levelMats[i].mat[1] == mat[1] && - m_levelMats[i].mat[2] == mat[2] && - m_levelMats[i].mat[3] == mat[3] ) return i; + if ( m_materials[i].mat[0] == mat[0] && + m_materials[i].mat[1] == mat[1] && + m_materials[i].mat[2] == mat[2] && + m_materials[i].mat[3] == mat[3] ) return i; } return -1; } -void Gfx::CTerrain::LevelSetDot(int x, int y, int id, char *mat) +void Gfx::CTerrain::SetMaterialPoint(int x, int y, int id, char *mat) { - TerrainMaterial* tm = LevelSearchMat(id); + TerrainMaterial* tm = FindMaterial(id); if (tm == nullptr) return; if ( tm->mat[0] != mat[0] || @@ -802,310 +737,310 @@ void Gfx::CTerrain::LevelSetDot(int x, int y, int id, char *mat) tm->mat[2] != mat[2] || tm->mat[3] != mat[3] ) // id incompatible with mat? { - int ii = LevelTestMat(mat); + int ii = FindMaterialByNeighbors(mat); if (ii == -1) return; - id = m_levelMats[ii].id; // looking for a id compatible with mat + id = m_materials[ii].id; // looking for a id compatible with mat } // Changes the point - m_levelDots[x+y*m_levelDotSize].id = id; - m_levelDots[x+y*m_levelDotSize].mat[0] = mat[0]; - m_levelDots[x+y*m_levelDotSize].mat[1] = mat[1]; - m_levelDots[x+y*m_levelDotSize].mat[2] = mat[2]; - m_levelDots[x+y*m_levelDotSize].mat[3] = mat[3]; + m_materialPoints[x+y*m_materialPointCount].id = id; + m_materialPoints[x+y*m_materialPointCount].mat[0] = mat[0]; + m_materialPoints[x+y*m_materialPointCount].mat[1] = mat[1]; + m_materialPoints[x+y*m_materialPointCount].mat[2] = mat[2]; + m_materialPoints[x+y*m_materialPointCount].mat[3] = mat[3]; // Changes the lower neighbor - if ( (x+0) >= 0 && (x+0) < m_levelDotSize && - (y-1) >= 0 && (y-1) < m_levelDotSize ) + if ( (x+0) >= 0 && (x+0) < m_materialPointCount && + (y-1) >= 0 && (y-1) < m_materialPointCount ) { - int i = (x+0)+(y-1)*m_levelDotSize; - if (m_levelDots[i].mat[0] != mat[2]) + int i = (x+0)+(y-1)*m_materialPointCount; + if (m_materialPoints[i].mat[0] != mat[2]) { - m_levelDots[i].mat[0] = mat[2]; - int ii = LevelTestMat(m_levelDots[i].mat); + m_materialPoints[i].mat[0] = mat[2]; + int ii = FindMaterialByNeighbors(m_materialPoints[i].mat); if (ii != -1) - m_levelDots[i].id = m_levelMats[ii].id; + m_materialPoints[i].id = m_materials[ii].id; } } // Modifies the left neighbor - if ( (x-1) >= 0 && (x-1) < m_levelDotSize && - (y+0) >= 0 && (y+0) < m_levelDotSize ) + if ( (x-1) >= 0 && (x-1) < m_materialPointCount && + (y+0) >= 0 && (y+0) < m_materialPointCount ) { - int i = (x-1)+(y+0)*m_levelDotSize; - if (m_levelDots[i].mat[1] != mat[3]) + int i = (x-1)+(y+0)*m_materialPointCount; + if (m_materialPoints[i].mat[1] != mat[3]) { - m_levelDots[i].mat[1] = mat[3]; - int ii = LevelTestMat(m_levelDots[i].mat); + m_materialPoints[i].mat[1] = mat[3]; + int ii = FindMaterialByNeighbors(m_materialPoints[i].mat); if (ii != -1) - m_levelDots[i].id = m_levelMats[ii].id; + m_materialPoints[i].id = m_materials[ii].id; } } // Changes the upper neighbor - if ( (x+0) >= 0 && (x+0) < m_levelDotSize && - (y+1) >= 0 && (y+1) < m_levelDotSize ) + if ( (x+0) >= 0 && (x+0) < m_materialPointCount && + (y+1) >= 0 && (y+1) < m_materialPointCount ) { - int i = (x+0)+(y+1)*m_levelDotSize; - if (m_levelDots[i].mat[2] != mat[0]) + int i = (x+0)+(y+1)*m_materialPointCount; + if (m_materialPoints[i].mat[2] != mat[0]) { - m_levelDots[i].mat[2] = mat[0]; - int ii = LevelTestMat(m_levelDots[i].mat); + m_materialPoints[i].mat[2] = mat[0]; + int ii = FindMaterialByNeighbors(m_materialPoints[i].mat); if (ii != -1) - m_levelDots[i].id = m_levelMats[ii].id; + m_materialPoints[i].id = m_materials[ii].id; } } // Changes the right neighbor - if ( (x+1) >= 0 && (x+1) < m_levelDotSize && - (y+0) >= 0 && (y+0) < m_levelDotSize ) + if ( (x+1) >= 0 && (x+1) < m_materialPointCount && + (y+0) >= 0 && (y+0) < m_materialPointCount ) { - int i = (x+1)+(y+0)*m_levelDotSize; - if ( m_levelDots[i].mat[3] != mat[1] ) + int i = (x+1)+(y+0)*m_materialPointCount; + if ( m_materialPoints[i].mat[3] != mat[1] ) { - m_levelDots[i].mat[3] = mat[1]; - int ii = LevelTestMat(m_levelDots[i].mat); + m_materialPoints[i].mat[3] = mat[1]; + int ii = FindMaterialByNeighbors(m_materialPoints[i].mat); if (ii != -1) - m_levelDots[i].id = m_levelMats[ii].id; + m_materialPoints[i].id = m_materials[ii].id; } } } -bool Gfx::CTerrain::LevelIfDot(int x, int y, int id, char *mat) +bool Gfx::CTerrain::CondChangeMaterialPoint(int x, int y, int id, char *mat) { char test[4]; // Compatible with lower neighbor? - if ( x+0 >= 0 && x+0 < m_levelDotSize && - y-1 >= 0 && y-1 < m_levelDotSize ) + if ( x+0 >= 0 && x+0 < m_materialPointCount && + y-1 >= 0 && y-1 < m_materialPointCount ) { test[0] = mat[2]; - test[1] = m_levelDots[(x+0)+(y-1)*m_levelDotSize].mat[1]; - test[2] = m_levelDots[(x+0)+(y-1)*m_levelDotSize].mat[2]; - test[3] = m_levelDots[(x+0)+(y-1)*m_levelDotSize].mat[3]; + test[1] = m_materialPoints[(x+0)+(y-1)*m_materialPointCount].mat[1]; + test[2] = m_materialPoints[(x+0)+(y-1)*m_materialPointCount].mat[2]; + test[3] = m_materialPoints[(x+0)+(y-1)*m_materialPointCount].mat[3]; - if ( LevelTestMat(test) == -1 ) return false; + if ( FindMaterialByNeighbors(test) == -1 ) return false; } // Compatible with left neighbor? - if ( x-1 >= 0 && x-1 < m_levelDotSize && - y+0 >= 0 && y+0 < m_levelDotSize ) + if ( x-1 >= 0 && x-1 < m_materialPointCount && + y+0 >= 0 && y+0 < m_materialPointCount ) { - test[0] = m_levelDots[(x-1)+(y+0)*m_levelDotSize].mat[0]; + test[0] = m_materialPoints[(x-1)+(y+0)*m_materialPointCount].mat[0]; test[1] = mat[3]; - test[2] = m_levelDots[(x-1)+(y+0)*m_levelDotSize].mat[2]; - test[3] = m_levelDots[(x-1)+(y+0)*m_levelDotSize].mat[3]; + test[2] = m_materialPoints[(x-1)+(y+0)*m_materialPointCount].mat[2]; + test[3] = m_materialPoints[(x-1)+(y+0)*m_materialPointCount].mat[3]; - if ( LevelTestMat(test) == -1 ) return false; + if ( FindMaterialByNeighbors(test) == -1 ) return false; } // Compatible with upper neighbor? - if ( x+0 >= 0 && x+0 < m_levelDotSize && - y+1 >= 0 && y+1 < m_levelDotSize ) + if ( x+0 >= 0 && x+0 < m_materialPointCount && + y+1 >= 0 && y+1 < m_materialPointCount ) { - test[0] = m_levelDots[(x+0)+(y+1)*m_levelDotSize].mat[0]; - test[1] = m_levelDots[(x+0)+(y+1)*m_levelDotSize].mat[1]; + test[0] = m_materialPoints[(x+0)+(y+1)*m_materialPointCount].mat[0]; + test[1] = m_materialPoints[(x+0)+(y+1)*m_materialPointCount].mat[1]; test[2] = mat[0]; - test[3] = m_levelDots[(x+0)+(y+1)*m_levelDotSize].mat[3]; + test[3] = m_materialPoints[(x+0)+(y+1)*m_materialPointCount].mat[3]; - if ( LevelTestMat(test) == -1 ) return false; + if ( FindMaterialByNeighbors(test) == -1 ) return false; } // Compatible with right neighbor? - if ( x+1 >= 0 && x+1 < m_levelDotSize && - y+0 >= 0 && y+0 < m_levelDotSize ) + if ( x+1 >= 0 && x+1 < m_materialPointCount && + y+0 >= 0 && y+0 < m_materialPointCount ) { - test[0] = m_levelDots[(x+1)+(y+0)*m_levelDotSize].mat[0]; - test[1] = m_levelDots[(x+1)+(y+0)*m_levelDotSize].mat[1]; - test[2] = m_levelDots[(x+1)+(y+0)*m_levelDotSize].mat[2]; + test[0] = m_materialPoints[(x+1)+(y+0)*m_materialPointCount].mat[0]; + test[1] = m_materialPoints[(x+1)+(y+0)*m_materialPointCount].mat[1]; + test[2] = m_materialPoints[(x+1)+(y+0)*m_materialPointCount].mat[2]; test[3] = mat[1]; - if ( LevelTestMat(test) == -1 ) return false; + if ( FindMaterialByNeighbors(test) == -1 ) return false; } - LevelSetDot(x, y, id, mat); // puts the point + SetMaterialPoint(x, y, id, mat); // puts the point return true; } -bool Gfx::CTerrain::LevelPutDot(int x, int y, int id) +bool Gfx::CTerrain::ChangeMaterialPoint(int x, int y, int id) { char mat[4]; - x /= m_brick/m_subdivMapping; - y /= m_brick/m_subdivMapping; + x /= m_brickCount/m_textureSubdivCount; + y /= m_brickCount/m_textureSubdivCount; - if ( x < 0 || x >= m_levelDotSize || - y < 0 || y >= m_levelDotSize ) return false; + if ( x < 0 || x >= m_materialPointCount || + y < 0 || y >= m_materialPointCount ) return false; - TerrainMaterial* tm = LevelSearchMat(id); + TerrainMaterial* tm = FindMaterial(id); if (tm == nullptr) return false; // Tries without changing neighbors. - if ( LevelIfDot(x, y, id, tm->mat) ) return true; + if ( CondChangeMaterialPoint(x, y, id, tm->mat) ) return true; // Tries changing a single neighbor (4x). - for (int up = 0; up < m_levelMatMax; up++) + for (int up = 0; up < m_maxMaterialID; up++) { mat[0] = up; mat[1] = tm->mat[1]; mat[2] = tm->mat[2]; mat[3] = tm->mat[3]; - if (LevelIfDot(x, y, id, mat)) return true; + if (CondChangeMaterialPoint(x, y, id, mat)) return true; } - for (int right = 0; right < m_levelMatMax; right++) + for (int right = 0; right < m_maxMaterialID; right++) { mat[0] = tm->mat[0]; mat[1] = right; mat[2] = tm->mat[2]; mat[3] = tm->mat[3]; - if (LevelIfDot(x, y, id, mat)) return true; + if (CondChangeMaterialPoint(x, y, id, mat)) return true; } - for (int down = 0; down < m_levelMatMax; down++) + for (int down = 0; down < m_maxMaterialID; down++) { mat[0] = tm->mat[0]; mat[1] = tm->mat[1]; mat[2] = down; mat[3] = tm->mat[3]; - if (LevelIfDot(x, y, id, mat)) return true; + if (CondChangeMaterialPoint(x, y, id, mat)) return true; } - for (int left = 0; left < m_levelMatMax; left++) + for (int left = 0; left < m_maxMaterialID; left++) { mat[0] = tm->mat[0]; mat[1] = tm->mat[1]; mat[2] = tm->mat[2]; mat[3] = left; - if (LevelIfDot(x, y, id, mat)) return true; + if (CondChangeMaterialPoint(x, y, id, mat)) return true; } // Tries changing two neighbors (6x). - for (int up = 0; up < m_levelMatMax; up++) + for (int up = 0; up < m_maxMaterialID; up++) { - for (int down = 0; down < m_levelMatMax; down++) + for (int down = 0; down < m_maxMaterialID; down++) { mat[0] = up; mat[1] = tm->mat[1]; mat[2] = down; mat[3] = tm->mat[3]; - if (LevelIfDot(x, y, id, mat)) return true; + if (CondChangeMaterialPoint(x, y, id, mat)) return true; } } - for (int right = 0; right < m_levelMatMax; right++) + for (int right = 0; right < m_maxMaterialID; right++) { - for (int left = 0; left < m_levelMatMax; left++) + for (int left = 0; left < m_maxMaterialID; left++) { mat[0] = tm->mat[0]; mat[1] = right; mat[2] = tm->mat[2]; mat[3] = left; - if (LevelIfDot(x, y, id, mat)) return true; + if (CondChangeMaterialPoint(x, y, id, mat)) return true; } } - for (int up = 0; up < m_levelMatMax; up++) + for (int up = 0; up < m_maxMaterialID; up++) { - for (int right = 0; right < m_levelMatMax; right++) + for (int right = 0; right < m_maxMaterialID; right++) { mat[0] = up; mat[1] = right; mat[2] = tm->mat[2]; mat[3] = tm->mat[3]; - if (LevelIfDot(x, y, id, mat)) return true; + if (CondChangeMaterialPoint(x, y, id, mat)) return true; } } - for (int right = 0; right < m_levelMatMax; right++) + for (int right = 0; right < m_maxMaterialID; right++) { - for (int down = 0; down < m_levelMatMax; down++) + for (int down = 0; down < m_maxMaterialID; down++) { mat[0] = tm->mat[0]; mat[1] = right; mat[2] = down; mat[3] = tm->mat[3]; - if (LevelIfDot(x, y, id, mat)) return true; + if (CondChangeMaterialPoint(x, y, id, mat)) return true; } } - for (int down = 0; down < m_levelMatMax; down++) + for (int down = 0; down < m_maxMaterialID; down++) { - for (int left = 0; left < m_levelMatMax; left++) + for (int left = 0; left < m_maxMaterialID; left++) { mat[0] = tm->mat[0]; mat[1] = tm->mat[1]; mat[2] = down; mat[3] = left; - if (LevelIfDot(x, y, id, mat)) return true; + if (CondChangeMaterialPoint(x, y, id, mat)) return true; } } - for (int up = 0; up < m_levelMatMax; up++) + for (int up = 0; up < m_maxMaterialID; up++) { - for (int left = 0; left < m_levelMatMax; left++) + for (int left = 0; left < m_maxMaterialID; left++) { mat[0] = up; mat[1] = tm->mat[1]; mat[2] = tm->mat[2]; mat[3] = left; - if (LevelIfDot(x, y, id, mat)) return true; + if (CondChangeMaterialPoint(x, y, id, mat)) return true; } } // Tries changing all the neighbors. - for (int up = 0; up < m_levelMatMax; up++) + for (int up = 0; up < m_maxMaterialID; up++) { - for (int right = 0; right < m_levelMatMax; right++) + for (int right = 0; right < m_maxMaterialID; right++) { - for (int down = 0; down < m_levelMatMax; down++) + for (int down = 0; down < m_maxMaterialID; down++) { - for (int left = 0; left < m_levelMatMax; left++) + for (int left = 0; left < m_maxMaterialID; left++) { mat[0] = up; mat[1] = right; mat[2] = down; mat[3] = left; - if (LevelIfDot(x, y, id, mat)) return true; + if (CondChangeMaterialPoint(x, y, id, mat)) return true; } } } } - GetLogger()->Error("LevelPutDot error\n"); + GetLogger()->Error("AddMaterialPoint error\n"); return false; } -bool Gfx::CTerrain::LevelInit(int id) +bool Gfx::CTerrain::InitMaterials(int id) { - TerrainMaterial* tm = LevelSearchMat(id); + TerrainMaterial* tm = FindMaterial(id); if (tm == nullptr) return false; - for (int i = 0; i < m_levelDotSize*m_levelDotSize; i++) + for (int i = 0; i < m_materialPointCount*m_materialPointCount; i++) { - m_levelDots[i].id = id; + m_materialPoints[i].id = id; for (int j = 0; j < 4; j++) - m_levelDots[i].mat[j] = tm->mat[j]; + m_materialPoints[i].mat[j] = tm->mat[j]; } return true; } -bool Gfx::CTerrain::LevelGenerate(int *id, float min, float max, - float slope, float freq, - Math::Vector center, float radius) +bool Gfx::CTerrain::GenerateMaterials(int *id, float min, float max, + float slope, float freq, + Math::Vector center, float radius) { static char random[100] = { @@ -1124,40 +1059,40 @@ bool Gfx::CTerrain::LevelGenerate(int *id, float min, float max, TerrainMaterial* tm = nullptr; int i = 0; - while ( id[i] != 0 ) + while (id[i] != 0) { - tm = LevelSearchMat(id[i++]); - if (tm == nullptr) return false; + tm = FindMaterial(id[i++]); + if (tm == nullptr) return false; } int numID = i; - int group = m_brick / m_subdivMapping; + int group = m_brickCount / m_textureSubdivCount; if (radius > 0.0f && radius < 5.0f) // just a square? { - float dim = (m_mosaic*m_brick*m_size)/2.0f; + float dim = (m_mosaicCount*m_brickCount*m_brickSize)/2.0f; - int xx = static_cast<int>((center.x+dim)/m_size); - int yy = static_cast<int>((center.z+dim)/m_size); + int xx = static_cast<int>((center.x+dim)/m_brickSize); + int yy = static_cast<int>((center.z+dim)/m_brickSize); int x = xx/group; int y = yy/group; - tm = LevelSearchMat(id[0]); + tm = FindMaterial(id[0]); if (tm != nullptr) - LevelSetDot(x, y, id[0], tm->mat); // puts the point + SetMaterialPoint(x, y, id[0], tm->mat); // puts the point } else { - for (int y = 0; y < m_levelDotSize; y++) + for (int y = 0; y < m_materialPointCount; y++) { - for (int x = 0; x < m_levelDotSize; x++) + for (int x = 0; x < m_materialPointCount; x++) { if (radius != 0.0f) { Math::Vector pos; - pos.x = (static_cast<float>(x)-m_levelDotSize/2.0f)*group*m_size; - pos.z = (static_cast<float>(y)-m_levelDotSize/2.0f)*group*m_size; + pos.x = (static_cast<float>(x)-m_materialPointCount/2.0f)*group*m_brickSize; + pos.z = (static_cast<float>(y)-m_materialPointCount/2.0f)*group*m_brickSize; if (Math::DistanceProjected(pos, center) > radius) continue; } @@ -1170,11 +1105,11 @@ bool Gfx::CTerrain::LevelGenerate(int *id, float min, float max, int xx = x*group + group/2; int yy = y*group + group/2; - if (LevelGetDot(xx, yy, min, max, slope)) + if (CheckMaterialPoint(xx, yy, min, max, slope)) { int rnd = random[(x%10)+(y%10)*10]; int ii = rnd % numID; - LevelPutDot(xx, yy, id[ii]); + ChangeMaterialPoint(xx, yy, id[ii]); } } } @@ -1183,66 +1118,59 @@ bool Gfx::CTerrain::LevelGenerate(int *id, float min, float max, return true; } -void Gfx::CTerrain::LevelOpenTable() +void Gfx::CTerrain::InitMaterialPoints() { - if (! m_levelText) return; - if (! m_levelDots.empty()) return; // already allocated + if (! m_useMaterials) return; + if (! m_materialPoints.empty()) return; // already allocated - m_levelDotSize = (m_mosaic*m_brick)/(m_brick/m_subdivMapping)+1; - std::vector<Gfx::DotLevel>(m_levelDotSize*m_levelDotSize).swap(m_levelDots); + m_materialPointCount = (m_mosaicCount*m_brickCount)/(m_brickCount/m_textureSubdivCount)+1; + std::vector<Gfx::TerrainMaterialPoint>(m_materialPointCount*m_materialPointCount).swap(m_materialPoints); - for (int i = 0; i < m_levelDotSize * m_levelDotSize; i++) + for (int i = 0; i < m_materialPointCount * m_materialPointCount; i++) { for (int j = 0; j < 4; j++) - m_levelDots[i].mat[j] = 0; + m_materialPoints[i].mat[j] = 0; } } -void Gfx::CTerrain::LevelCloseTable() +void Gfx::CTerrain::FlushMaterialPoints() { - m_levelDots.clear(); + m_materialPoints.clear(); } -bool Gfx::CTerrain::CreateSquare(bool multiRes, int x, int y) +bool Gfx::CTerrain::CreateSquare(int x, int y) { Gfx::Material mat; mat.diffuse = Gfx::Color(1.0f, 1.0f, 1.0f); mat.ambient = Gfx::Color(0.0f, 0.0f, 0.0f); int objRank = m_engine->CreateObject(); - m_engine->SetObjectType(objRank, Gfx::ENG_OBJTYPE_TERRAIN); // it is a terrain + m_engine->SetObjectType(objRank, Gfx::ENG_OBJTYPE_TERRAIN); - m_objRank[x+y*m_mosaic] = objRank; + m_objRanks[x+y*m_mosaicCount] = objRank; - if (multiRes) + float min = 0.0f; + float max = m_vision; + max *= m_engine->GetClippingDistance(); + for (int step = 0; step < m_depth; step++) { - float min = 0.0f; - float max = m_vision; - max *= m_engine->GetClippingDistance(); - for (int step = 0; step < m_depth; step++) - { - CreateMosaic(x, y, 1 << step, objRank, mat, min, max); - min = max; - max *= 2; - if (step == m_depth-1) max = Math::HUGE_NUM; - } - } - else - { - CreateMosaic(x, y, 1, objRank, mat, 0.0f, Math::HUGE_NUM); + CreateMosaic(x, y, 1 << step, objRank, mat, min, max); + min = max; + max *= 2; + if (step == m_depth-1) max = Math::HUGE_NUM; } return true; } -bool Gfx::CTerrain::CreateObjects(bool multiRes) +bool Gfx::CTerrain::CreateObjects() { AdjustRelief(); - for (int y = 0; y < m_mosaic; y++) + for (int y = 0; y < m_mosaicCount; y++) { - for (int x = 0; x < m_mosaic; x++) - CreateSquare(multiRes, x, y); + for (int x = 0; x < m_mosaicCount; x++) + CreateSquare(x, y); } return true; @@ -1251,29 +1179,29 @@ bool Gfx::CTerrain::CreateObjects(bool multiRes) /** ATTENTION: ok only with m_depth = 2! */ bool Gfx::CTerrain::Terraform(const Math::Vector &p1, const Math::Vector &p2, float height) { - float dim = (m_mosaic*m_brick*m_size)/2.0f; + float dim = (m_mosaicCount*m_brickCount*m_brickSize)/2.0f; Math::IntPoint tp1, tp2; - tp1.x = static_cast<int>((p1.x+dim+m_size/2.0f)/m_size); - tp1.y = static_cast<int>((p1.z+dim+m_size/2.0f)/m_size); - tp2.x = static_cast<int>((p2.x+dim+m_size/2.0f)/m_size); - tp2.y = static_cast<int>((p2.z+dim+m_size/2.0f)/m_size); + tp1.x = static_cast<int>((p1.x+dim+m_brickSize/2.0f)/m_brickSize); + tp1.y = static_cast<int>((p1.z+dim+m_brickSize/2.0f)/m_brickSize); + tp2.x = static_cast<int>((p2.x+dim+m_brickSize/2.0f)/m_brickSize); + tp2.y = static_cast<int>((p2.z+dim+m_brickSize/2.0f)/m_brickSize); if (tp1.x > tp2.x) { - int x = tp1.x; + int x = tp1.x; tp1.x = tp2.x; tp2.x = x; } if (tp1.y > tp2.y) { - int y = tp1.y; + int y = tp1.y; tp1.y = tp2.y; tp2.y = y; } - int size = (m_mosaic*m_brick)+1; + int size = (m_mosaicCount*m_brickCount)+1; // Calculates the current average height float avg = 0.0f; @@ -1295,13 +1223,13 @@ bool Gfx::CTerrain::Terraform(const Math::Vector &p1, const Math::Vector &p2, fl { m_relief[x+y*size] = avg+height; - if (x % m_brick == 0 && y % m_depth != 0) + if (x % m_brickCount == 0 && y % m_depth != 0) { m_relief[(x+0)+(y-1)*size] = avg+height; m_relief[(x+0)+(y+1)*size] = avg+height; } - if (y % m_brick == 0 && x % m_depth != 0) + if (y % m_brickCount == 0 && x % m_depth != 0) { m_relief[(x-1)+(y+0)*size] = avg+height; m_relief[(x+1)+(y+0)*size] = avg+height; @@ -1311,22 +1239,22 @@ bool Gfx::CTerrain::Terraform(const Math::Vector &p1, const Math::Vector &p2, fl AdjustRelief(); Math::IntPoint pp1, pp2; - pp1.x = (tp1.x-2)/m_brick; - pp1.y = (tp1.y-2)/m_brick; - pp2.x = (tp2.x+1)/m_brick; - pp2.y = (tp2.y+1)/m_brick; + pp1.x = (tp1.x-2)/m_brickCount; + pp1.y = (tp1.y-2)/m_brickCount; + pp2.x = (tp2.x+1)/m_brickCount; + pp2.y = (tp2.y+1)/m_brickCount; - if (pp1.x < 0 ) pp1.x = 0; - if (pp1.x >= m_mosaic) pp1.x = m_mosaic-1; - if (pp1.y < 0 ) pp1.y = 0; - if (pp1.y >= m_mosaic) pp1.y = m_mosaic-1; + if (pp1.x < 0 ) pp1.x = 0; + if (pp1.x >= m_mosaicCount) pp1.x = m_mosaicCount-1; + if (pp1.y < 0 ) pp1.y = 0; + if (pp1.y >= m_mosaicCount) pp1.y = m_mosaicCount-1; for (int y = pp1.y; y <= pp2.y; y++) { for (int x = pp1.x; x <= pp2.x; x++) { - m_engine->DeleteObject(m_objRank[x+y*m_mosaic]); - CreateSquare(m_multiText, x, y); // recreates the square + m_engine->DeleteObject(m_objRanks[x+y*m_mosaicCount]); + CreateSquare(x, y); // recreates the square } } m_engine->Update(); @@ -1355,37 +1283,37 @@ float Gfx::CTerrain::GetCoarseSlope(const Math::Vector &pos) { if (m_relief.empty()) return 0.0f; - float dim = (m_mosaic*m_brick*m_size)/2.0f; + float dim = (m_mosaicCount*m_brickCount*m_brickSize)/2.0f; - int x = static_cast<int>((pos.x+dim)/m_size); - int y = static_cast<int>((pos.z+dim)/m_size); + int x = static_cast<int>((pos.x+dim)/m_brickSize); + int y = static_cast<int>((pos.z+dim)/m_brickSize); - if ( x < 0 || x >= m_mosaic*m_brick || - y < 0 || y >= m_mosaic*m_brick ) return 0.0f; + if ( x < 0 || x >= m_mosaicCount*m_brickCount || + y < 0 || y >= m_mosaicCount*m_brickCount ) return 0.0f; float level[4] = { - m_relief[(x+0)+(y+0)*(m_mosaic*m_brick+1)], - m_relief[(x+1)+(y+0)*(m_mosaic*m_brick+1)], - m_relief[(x+0)+(y+1)*(m_mosaic*m_brick+1)], - m_relief[(x+1)+(y+1)*(m_mosaic*m_brick+1)], + m_relief[(x+0)+(y+0)*(m_mosaicCount*m_brickCount+1)], + m_relief[(x+1)+(y+0)*(m_mosaicCount*m_brickCount+1)], + m_relief[(x+0)+(y+1)*(m_mosaicCount*m_brickCount+1)], + m_relief[(x+1)+(y+1)*(m_mosaicCount*m_brickCount+1)], }; float min = Math::Min(level[0], level[1], level[2], level[3]); float max = Math::Max(level[0], level[1], level[2], level[3]); - return atanf((max-min)/m_size); + return atanf((max-min)/m_brickSize); } bool Gfx::CTerrain::GetNormal(Math::Vector &n, const Math::Vector &p) { - float dim = (m_mosaic*m_brick*m_size)/2.0f; + float dim = (m_mosaicCount*m_brickCount*m_brickSize)/2.0f; - int x = static_cast<int>((p.x+dim)/m_size); - int y = static_cast<int>((p.z+dim)/m_size); + int x = static_cast<int>((p.x+dim)/m_brickSize); + int y = static_cast<int>((p.z+dim)/m_brickSize); - if ( x < 0 || x > m_mosaic*m_brick || - y < 0 || y > m_mosaic*m_brick ) return false; + if ( x < 0 || x > m_mosaicCount*m_brickCount || + y < 0 || y > m_mosaicCount*m_brickCount ) return false; Math::Vector p1 = GetVector(x+0, y+0); Math::Vector p2 = GetVector(x+1, y+0); @@ -1400,23 +1328,23 @@ bool Gfx::CTerrain::GetNormal(Math::Vector &n, const Math::Vector &p) return true; } -float Gfx::CTerrain::GetFloorLevel(const Math::Vector &p, bool brut, bool water) +float Gfx::CTerrain::GetFloorLevel(const Math::Vector &pos, bool brut, bool water) { - float dim = (m_mosaic*m_brick*m_size)/2.0f; + float dim = (m_mosaicCount*m_brickCount*m_brickSize)/2.0f; - int x = static_cast<int>((p.x+dim)/m_size); - int y = static_cast<int>((p.z+dim)/m_size); + int x = static_cast<int>((pos.x+dim)/m_brickSize); + int y = static_cast<int>((pos.z+dim)/m_brickSize); - if ( x < 0 || x > m_mosaic*m_brick || - y < 0 || y > m_mosaic*m_brick ) return false; + if ( x < 0 || x > m_mosaicCount*m_brickCount || + y < 0 || y > m_mosaicCount*m_brickCount ) return false; Math::Vector p1 = GetVector(x+0, y+0); Math::Vector p2 = GetVector(x+1, y+0); Math::Vector p3 = GetVector(x+0, y+1); Math::Vector p4 = GetVector(x+1, y+1); - Math::Vector ps = p; - if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) ) + Math::Vector ps = pos; + if ( fabs(pos.z-p2.z) < fabs(pos.x-p2.x) ) { if ( !IntersectY(p1, p2, p3, ps) ) return 0.0f; } @@ -1436,25 +1364,23 @@ float Gfx::CTerrain::GetFloorLevel(const Math::Vector &p, bool brut, bool water) return ps.y; } - -/** This height is positive when you are above the ground */ -float Gfx::CTerrain::GetFloorHeight(const Math::Vector &p, bool brut, bool water) +float Gfx::CTerrain::GetHeightToFloor(const Math::Vector &pos, bool brut, bool water) { - float dim = (m_mosaic*m_brick*m_size)/2.0f; + float dim = (m_mosaicCount*m_brickCount*m_brickSize)/2.0f; - int x = static_cast<int>((p.x+dim)/m_size); - int y = static_cast<int>((p.z+dim)/m_size); + int x = static_cast<int>((pos.x+dim)/m_brickSize); + int y = static_cast<int>((pos.z+dim)/m_brickSize); - if ( x < 0 || x > m_mosaic*m_brick || - y < 0 || y > m_mosaic*m_brick ) return false; + if ( x < 0 || x > m_mosaicCount*m_brickCount || + y < 0 || y > m_mosaicCount*m_brickCount ) return false; Math::Vector p1 = GetVector(x+0, y+0); Math::Vector p2 = GetVector(x+1, y+0); Math::Vector p3 = GetVector(x+0, y+1); Math::Vector p4 = GetVector(x+1, y+1); - Math::Vector ps = p; - if ( fabs(p.z-p2.z) < fabs(p.x-p2.x) ) + Math::Vector ps = pos; + if ( fabs(pos.z-p2.z) < fabs(pos.x-p2.x) ) { if ( !IntersectY(p1, p2, p3, ps) ) return 0.0f; } @@ -1468,76 +1394,114 @@ float Gfx::CTerrain::GetFloorHeight(const Math::Vector &p, bool brut, bool water if (water) // not going underwater? { float level = m_water->GetLevel(); - if ( ps.y < level ) ps.y = level; // not under water + if (ps.y < level ) ps.y = level; // not under water } - return p.y-ps.y; + return pos.y-ps.y; } -bool Gfx::CTerrain::MoveOnFloor(Math::Vector &p, bool brut, bool water) +bool Gfx::CTerrain::AdjustToFloor(Math::Vector &pos, bool brut, bool water) { - float dim = (m_mosaic*m_brick*m_size)/2.0f; + float dim = (m_mosaicCount*m_brickCount*m_brickSize)/2.0f; - int x = static_cast<int>((p.x + dim) / m_size); - int y = static_cast<int>((p.z + dim) / m_size); + int x = static_cast<int>((pos.x + dim) / m_brickSize); + int y = static_cast<int>((pos.z + dim) / m_brickSize); - if ( x < 0 || x > m_mosaic*m_brick || - y < 0 || y > m_mosaic*m_brick ) return false; + if ( x < 0 || x > m_mosaicCount*m_brickCount || + y < 0 || y > m_mosaicCount*m_brickCount ) return false; Math::Vector p1 = GetVector(x+0, y+0); Math::Vector p2 = GetVector(x+1, y+0); Math::Vector p3 = GetVector(x+0, y+1); Math::Vector p4 = GetVector(x+1, y+1); - if (fabs(p.z - p2.z) < fabs(p.x - p2.x)) + if (fabs(pos.z - p2.z) < fabs(pos.x - p2.x)) { - if (! Math::IntersectY(p1, p2, p3, p)) return false; + if (! Math::IntersectY(p1, p2, p3, pos)) return false; } else { - if (! Math::IntersectY(p2, p4, p3, p)) return false; + if (! Math::IntersectY(p2, p4, p3, pos)) return false; } - if (! brut) AdjustBuildingLevel(p); + if (! brut) AdjustBuildingLevel(pos); if (water) // not going underwater? { float level = m_water->GetLevel(); - if (p.y < level) p.y = level; // not under water + if (pos.y < level) pos.y = level; // not under water } return true; } - -/** Returns false if the initial coordinate was too far */ -bool Gfx::CTerrain::ValidPosition(Math::Vector &p, float marging) +/** + * @returns \c false if the initial coordinate was outside terrain area; \c true otherwise + */ +bool Gfx::CTerrain::AdjustToStandardBounds(Math::Vector& pos) { bool ok = true; - float limit = m_mosaic*m_brick*m_size/2.0f - marging; + // TODO: _TEEN ... * 0.98f; + float limit = (m_mosaicCount*m_brickCount*m_brickSize)/2.0f*0.92f; - if (p.x < -limit) + if (pos.x < -limit) { - p.x = -limit; + pos.x = -limit; ok = false; } - if (p.z < -limit) + if (pos.z < -limit) { - p.z = -limit; + pos.z = -limit; ok = false; } - if (p.x > limit) + if (pos.x > limit) { - p.x = limit; + pos.x = limit; ok = false; } - if (p.z > limit) + if (pos.z > limit) { - p.z = limit; + pos.z = limit; + ok = false; + } + + return ok; +} + +/** + * @param margin margin to the terrain border + * @returns \c false if the initial coordinate was outside terrain area; \c true otherwise + */ +bool Gfx::CTerrain::AdjustToBounds(Math::Vector& pos, float margin) +{ + bool ok = true; + float limit = m_mosaicCount*m_brickCount*m_brickSize/2.0f - margin; + + if (pos.x < -limit) + { + pos.x = -limit; + ok = false; + } + + if (pos.z < -limit) + { + pos.z = -limit; + ok = false; + } + + if (pos.x > limit) + { + pos.x = limit; + ok = false; + } + + if (pos.z > limit) + { + pos.z = limit; ok = false; } @@ -1664,46 +1628,41 @@ void Gfx::CTerrain::AdjustBuildingLevel(Math::Vector &p) } } - -// returns the hardness of the ground in a given place. -// The hardness determines the noise (SOUND_STEP and SOUND_BOUM). - float Gfx::CTerrain::GetHardness(const Math::Vector &p) { float factor = GetBuildingFactor(p); - if (factor != 1.0f) return 1.0f; // on building + if (factor != 1.0f) return 1.0f; // on building level - if (m_levelDots.empty()) return m_defHardness; + if (m_materialPoints.empty()) return m_defaultHardness; - float dim = (m_mosaic*m_brick*m_size)/2.0f; + float dim = (m_mosaicCount*m_brickCount*m_brickSize)/2.0f; int x, y; - x = static_cast<int>((p.x+dim)/m_size); - y = static_cast<int>((p.z+dim)/m_size); + x = static_cast<int>((p.x+dim)/m_brickSize); + y = static_cast<int>((p.z+dim)/m_brickSize); - if ( x < 0 || x > m_mosaic*m_brick || - y < 0 || y > m_mosaic*m_brick ) return m_defHardness; + if ( x < 0 || x > m_mosaicCount*m_brickCount || + y < 0 || y > m_mosaicCount*m_brickCount ) return m_defaultHardness; - x /= m_brick/m_subdivMapping; - y /= m_brick/m_subdivMapping; + x /= m_brickCount/m_textureSubdivCount; + y /= m_brickCount/m_textureSubdivCount; - if ( x < 0 || x >= m_levelDotSize || - y < 0 || y >= m_levelDotSize ) return m_defHardness; + if ( x < 0 || x >= m_materialPointCount || + y < 0 || y >= m_materialPointCount ) return m_defaultHardness; - int id = m_levelDots[x+y*m_levelDotSize].id; - TerrainMaterial* tm = LevelSearchMat(id); - if (tm == nullptr) return m_defHardness; + int id = m_materialPoints[x+y*m_materialPointCount].id; + TerrainMaterial* tm = FindMaterial(id); + if (tm == nullptr) return m_defaultHardness; return tm->hardness; } -void Gfx::CTerrain::GroundFlat(Math::Vector pos) +void Gfx::CTerrain::ShowFlatGround(Math::Vector pos) { - static char table[41*41]; - + static char table[41*41] = { 1 }; - float rapport = 3200.0f/1024.0f; + float radius = 3200.0f/1024.0f; for (int y = 0; y <= 40; y++) { @@ -1713,16 +1672,16 @@ void Gfx::CTerrain::GroundFlat(Math::Vector pos) table[i] = 0; Math::Vector p; - p.x = (x-20)*rapport; - p.z = (y-20)*rapport; + p.x = (x-20)*radius; + p.z = (y-20)*radius; p.y = 0.0f; - if (Math::Point(p.x, p.y).Length() > 20.0f*rapport) + if (Math::Point(p.x, p.y).Length() > 20.0f*radius) continue; float angle = GetFineSlope(pos+p); - if (angle < FLATLIMIT) + if (angle < Gfx::TERRAIN_FLATLIMIT) table[i] = 1; else table[i] = 2; @@ -1735,7 +1694,7 @@ void Gfx::CTerrain::GroundFlat(Math::Vector pos) float Gfx::CTerrain::GetFlatZoneRadius(Math::Vector center, float max) { float angle = GetFineSlope(center); - if (angle >= Gfx::FLATLIMIT) + if (angle >= Gfx::TERRAIN_FLATLIMIT) return 0.0f; float ref = GetFloorLevel(center, true); |