summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/image.cpp35
-rw-r--r--src/common/image.h6
-rw-r--r--src/graphics/core/color.h29
-rw-r--r--src/graphics/engine/terrain.cpp87
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);