diff options
-rw-r--r-- | src/common/image.cpp | 35 | ||||
-rw-r--r-- | src/common/image.h | 6 | ||||
-rw-r--r-- | src/graphics/core/color.h | 29 | ||||
-rw-r--r-- | src/graphics/engine/terrain.cpp | 87 |
4 files changed, 106 insertions, 51 deletions
diff --git a/src/common/image.cpp b/src/common/image.cpp index 50f6eee..6a2ab0e 100644 --- a/src/common/image.cpp +++ b/src/common/image.cpp @@ -190,7 +190,7 @@ Math::IntPoint CImage::GetSize() const * \param pixel pixel coords (range x: 0..width-1 y: 0..height-1) * \returns color */ -Gfx::Color CImage::GetPixel(Math::IntPoint pixel) +Gfx::IntColor CImage::GetPixelInt(Math::IntPoint pixel) { assert(m_data != nullptr); assert(pixel.x >= 0 || pixel.x <= m_data->surface->w); @@ -229,16 +229,28 @@ Gfx::Color CImage::GetPixel(Math::IntPoint pixel) Uint8 r = 0, g = 0, b = 0, a = 0; SDL_GetRGBA(u, m_data->surface->format, &r, &g, &b, &a); - return Gfx::Color(r / 255.0f, g / 255.0f, b / 255.0f, a / 255.0f); + return Gfx::IntColor(r, g, b, a); +} + +/** + * Image must be valid and pixel coords in valid range. + * + * \param pixel pixel coords (range x: 0..width-1 y: 0..height-1) + * \returns color + */ +Gfx::Color CImage::GetPixel(Math::IntPoint pixel) +{ + return Gfx::IntColorToColor(GetPixelInt(pixel)); } + /** * Image must be valid and pixel coords in valid range. * * \param pixel pixel coords (range x: 0..width-1 y: 0..height-1) * \param color color */ -void CImage::SetPixel(Math::IntPoint pixel, Gfx::Color color) +void CImage::SetPixelInt(Math::IntPoint pixel, Gfx::IntColor color) { assert(m_data != nullptr); assert(pixel.x >= 0 || pixel.x <= m_data->surface->w); @@ -248,11 +260,7 @@ void CImage::SetPixel(Math::IntPoint pixel, Gfx::Color color) int index = pixel.y * m_data->surface->pitch + pixel.x * bpp; Uint8* p = &static_cast<Uint8*>(m_data->surface->pixels)[index]; - Uint8 r = static_cast<Uint8>(color.r * 255.0f); - Uint8 g = static_cast<Uint8>(color.g * 255.0f); - Uint8 b = static_cast<Uint8>(color.b * 255.0f); - Uint8 a = static_cast<Uint8>(color.a * 255.0f); - Uint32 u = SDL_MapRGBA(m_data->surface->format, r, g, b, a); + Uint32 u = SDL_MapRGBA(m_data->surface->format, color.r, color.g, color.b, color.a); switch(bpp) { @@ -288,6 +296,17 @@ void CImage::SetPixel(Math::IntPoint pixel, Gfx::Color color) } } +/** + * Image must be valid and pixel coords in valid range. + * + * \param pixel pixel coords (range x: 0..width-1 y: 0..height-1) + * \param color color + */ +void CImage::SetPixel(Math::IntPoint pixel, Gfx::Color color) +{ + SetPixelInt(pixel, Gfx::ColorToIntColor(color)); +} + std::string CImage::GetError() { return m_error; diff --git a/src/common/image.h b/src/common/image.h index 93c7cab..3391bdb 100644 --- a/src/common/image.h +++ b/src/common/image.h @@ -78,9 +78,15 @@ public: //! Sets the color at given pixel void SetPixel(Math::IntPoint pixel, Gfx::Color color); + //! Sets the precise color at given pixel + void SetPixelInt(Math::IntPoint pixel, Gfx::IntColor color); + //! Returns the color at given pixel Gfx::Color GetPixel(Math::IntPoint pixel); + //! Returns the precise color at given pixel + Gfx::IntColor GetPixelInt(Math::IntPoint pixel); + //! Loads an image from the specified file bool Load(const std::string &fileName); diff --git a/src/graphics/core/color.h b/src/graphics/core/color.h index 4b152c1..0bec7e9 100644 --- a/src/graphics/core/color.h +++ b/src/graphics/core/color.h @@ -79,6 +79,35 @@ struct Color }; /** + * \struct IntColor + * \brief Color with integer values + * + * May be used for precise pixel manipulations. + */ +struct IntColor +{ + //! Red, green, blue and alpha components + unsigned char r, g, b, a; + + //! Constructor; default values are (0,0,0,0) = black + explicit IntColor(unsigned char aR = 0, unsigned char aG = 0, unsigned char aB = 0, unsigned char aA = 0) + : r(aR), g(aG), b(aB), a(aA) {} +}; + +inline Color IntColorToColor(IntColor color) +{ + return Color(color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, color.a / 255.0f); +} + +inline IntColor ColorToIntColor(Color color) +{ + return IntColor(static_cast<unsigned char>(color.r * 255.0f), + static_cast<unsigned char>(color.g * 255.0f), + static_cast<unsigned char>(color.b * 255.0f), + static_cast<unsigned char>(color.a * 255.0f)); +} + +/** * \struct ColorHSV * \brief HSV color */ diff --git a/src/graphics/engine/terrain.cpp b/src/graphics/engine/terrain.cpp index d2ddecc..9a82c1f 100644 --- a/src/graphics/engine/terrain.cpp +++ b/src/graphics/engine/terrain.cpp @@ -74,7 +74,7 @@ CTerrain::~CTerrain() } bool CTerrain::Generate(int mosaicCount, int brickCountPow2, float brickSize, - float vision, int depth, float hardness) + float vision, int depth, float hardness) { m_mosaicCount = mosaicCount; m_brickCount = 1 << brickCountPow2; @@ -162,8 +162,8 @@ void CTerrain::FlushMaterials() } void CTerrain::AddMaterial(int id, const std::string& texName, const Math::Point &uv, - int up, int right, int down, int left, - float hardness) + int up, int right, int down, int left, + float hardness) { InitMaterialPoints(); @@ -207,25 +207,41 @@ bool CTerrain::LoadResources(const std::string& fileName) ImageData *data = img.GetData(); - int size = (m_mosaicCount*m_brickCount)+1; - - m_resources.clear(); + int size = (m_mosaicCount*m_brickCount)+1; - std::vector<unsigned char>(3*size*size).swap(m_resources); + std::vector<unsigned char>(size*size).swap(m_resources); - if ( (data->surface->w != size) || (data->surface->h != size) || - (data->surface->format->BytesPerPixel != 3) ) + if ( (data->surface->w != size) || (data->surface->h != size) ) { GetLogger()->Error("Invalid resource file\n"); return false; } - unsigned char* pixels = static_cast<unsigned char*>(data->surface->pixels); - int pitch = data->surface->pitch; - - for (int y = 0; y < size; y++) + for (int x = 0; x < size; ++x) { - memcpy(&m_resources[3*size*y], &pixels[pitch*y], 3*size); + for (int y = 0; y < size; ++y) + { + Gfx::IntColor pixel = img.GetPixelInt(Math::IntPoint(x, size - y - 1)); + TerrainRes res = TR_NULL; + + // values from original bitmap palette + if (pixel.r == 255 && pixel.g == 0 && pixel.b == 0) + res = TR_STONE; + else if (pixel.r == 255 && pixel.g == 255 && pixel.b == 0) + res = TR_URANIUM; + else if (pixel.r == 0 && pixel.g == 255 && pixel.b == 0) + res = TR_POWER; + else if (pixel.r == 0 && pixel.g == 204 && pixel.b == 0) + res = TR_KEY_A; + else if (pixel.r == 51 && pixel.g == 204 && pixel.b == 0) + res = TR_KEY_B; + else if (pixel.r == 102 && pixel.g == 204 && pixel.b == 0) + res = TR_KEY_C; + else if (pixel.r == 153 && pixel.g == 204 && pixel.b == 0) + res = TR_KEY_D; + + m_resources[x+size*y] = static_cast<unsigned char>(res); + } } return true; @@ -243,23 +259,9 @@ TerrainRes CTerrain::GetResource(const Math::Vector &p) y < 0 || y > m_mosaicCount*m_brickCount ) return TR_NULL; - 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]; - int resB = m_resources[3*x+3*size*(size-y-1)+2]; - - if (resR == 255 && resG == 0 && resB == 0) return TR_STONE; - if (resR == 255 && resG == 255 && resB == 0) return TR_URANIUM; - if (resR == 0 && resG == 255 && resB == 0) return TR_POWER; - - // TODO key res values - //if (ress == 24) return TR_KEY_A; // ~green? - //if (ress == 25) return TR_KEY_B; // ~green? - //if (ress == 26) return TR_KEY_C; // ~green? - //if (ress == 27) return TR_KEY_D; // ~green? + int size = (m_mosaicCount*m_brickCount)+1; - return TR_NULL; + return static_cast<TerrainRes>( m_resources[x+size*y] ); } void CTerrain::FlushRelief() @@ -287,22 +289,21 @@ bool CTerrain::LoadRelief(const std::string &fileName, float scaleRelief, int size = (m_mosaicCount*m_brickCount)+1; - if ( (data->surface->w != size) || (data->surface->h != size) || - (data->surface->format->BytesPerPixel != 3) ) + if ( (data->surface->w != size) || (data->surface->h != size) ) { GetLogger()->Error("Invalid relief file!\n"); 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+pitch*(size-y-1)]) * scaleRelief; + Gfx::IntColor color = img.GetPixelInt(Math::IntPoint(x, size - y - 1)); + + float avg = (color.r + color.g + color.b) / 3.0f; // to be sure it is grayscale + float level = (255.0f - avg) * scaleRelief; float dist = Math::Max(fabs(static_cast<float>(x-size/2)), fabs(static_cast<float>(y-size/2))); @@ -492,8 +493,8 @@ VertexTex2 CTerrain::GetVertex(int x, int y, int step) +-------------------> x \endverbatim */ bool CTerrain::CreateMosaic(int ox, int oy, int step, int objRank, - const Material &mat, - float min, float max) + const Material &mat, + float min, float max) { std::string texName1; std::string texName2; @@ -1057,8 +1058,8 @@ bool CTerrain::InitMaterials(int id) } bool CTerrain::GenerateMaterials(int *id, float min, float max, - float slope, float freq, - Math::Vector center, float radius) + float slope, float freq, + Math::Vector center, float radius) { static char random[100] = { @@ -1460,7 +1461,7 @@ bool CTerrain::AdjustToStandardBounds(Math::Vector& pos) { bool ok = true; - // TODO: _TEEN ... * 0.98f; + // In _TEEN there used to be a limit of 0.98f float limit = (m_mosaicCount*m_brickCount*m_brickSize)/2.0f*0.92f; if (pos.x < -limit) @@ -1718,14 +1719,14 @@ float CTerrain::GetFlatZoneRadius(Math::Vector center, float max) float ref = GetFloorLevel(center, true); Math::Point c(center.x, center.z); float radius = 1.0f; - + while (radius <= max) { angle = 0.0f; int nb = static_cast<int>(2.0f*Math::PI*radius); if (nb < 8) nb = 8; - Math::Point p (center.x+radius, center.z); + Math::Point p (center.x+radius, center.z); for (int i = 0; i < nb; i++) { Math::Point result = Math::RotatePoint(c, angle, p); |