summaryrefslogtreecommitdiffstats
path: root/src/graphics/engine
diff options
context:
space:
mode:
Diffstat (limited to 'src/graphics/engine')
-rw-r--r--src/graphics/engine/engine.cpp206
-rw-r--r--src/graphics/engine/engine.h26
2 files changed, 186 insertions, 46 deletions
diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp
index c094c63..7e00134 100644
--- a/src/graphics/engine/engine.cpp
+++ b/src/graphics/engine/engine.cpp
@@ -181,9 +181,6 @@ CEngine::CEngine(CInstanceManager *iMan, CApplication *app)
m_alphaMode = 1;
- m_forceStateColor = true;
- m_stateColor = false;
-
m_updateGeometry = false;
m_interfaceMode = false;
@@ -1851,13 +1848,12 @@ void CEngine::SetState(int state, const Color& color)
m_device->SetRenderState(RENDER_STATE_BLENDING, true);
m_device->SetBlendFunc(BLEND_ONE, BLEND_INV_SRC_COLOR);
- m_device->SetTextureFactor(color);
-
TextureStageParams params;
params.colorOperation = TEX_MIX_OPER_MODULATE;
params.colorArg1 = TEX_MIX_ARG_TEXTURE;
params.colorArg2 = TEX_MIX_ARG_FACTOR;
params.alphaOperation = TEX_MIX_OPER_DEFAULT; // TODO: replace with src color ?
+ params.factor = color;
m_device->SetTextureEnabled(0, true);
m_device->SetTextureStageParams(0, params);
@@ -1871,13 +1867,12 @@ void CEngine::SetState(int state, const Color& color)
m_device->SetRenderState(RENDER_STATE_BLENDING, true);
m_device->SetBlendFunc(BLEND_DST_COLOR, BLEND_ZERO);
- m_device->SetTextureFactor(color.Inverse());
-
TextureStageParams params;
params.colorOperation = TEX_MIX_OPER_ADD;
params.colorArg1 = TEX_MIX_ARG_TEXTURE;
params.colorArg2 = TEX_MIX_ARG_FACTOR;
params.alphaOperation = TEX_MIX_OPER_DEFAULT; // TODO: replace with src color ?
+ params.factor = color.Inverse();
m_device->SetTextureEnabled(0, true);
m_device->SetTextureStageParams(0, params);
@@ -1963,14 +1958,13 @@ void CEngine::SetState(int state, const Color& color)
m_device->SetAlphaTestFunc(COMP_FUNC_GREATER, 0.5f);
- m_device->SetTextureFactor(color);
-
TextureStageParams params;
params.colorOperation = TEX_MIX_OPER_MODULATE;
params.colorArg1 = TEX_MIX_ARG_TEXTURE;
params.colorArg2 = TEX_MIX_ARG_SRC_COLOR;
params.alphaOperation = TEX_MIX_OPER_REPLACE;
params.alphaArg1 = TEX_MIX_ARG_TEXTURE;
+ params.factor = color;
m_device->SetTextureEnabled(0, true);
m_device->SetTextureStageParams(0, params);
@@ -2080,7 +2074,7 @@ void CEngine::SetViewParams(const Math::Vector& eyePt, const Math::Vector& looka
m_sound->SetListener(eyePt, lookatPt);
}
-Texture CEngine::CreateTexture(const std::string& texName, const TextureCreateParams& params)
+Texture CEngine::CreateTexture(const std::string& texName, const TextureCreateParams& params, CImage* image)
{
if (texName.empty())
return Texture(); // invalid texture
@@ -2088,18 +2082,25 @@ Texture CEngine::CreateTexture(const std::string& texName, const TextureCreatePa
if (m_texBlacklist.find(texName) != m_texBlacklist.end())
return Texture(); // invalid texture
- // TODO: detect alpha channel?
+ Texture tex;
- CImage img;
- if (! img.Load(m_app->GetDataFilePath(DIR_TEXTURE, texName)))
+ if (image == nullptr)
{
- std::string error = img.GetError();
- GetLogger()->Error("Couldn't load texture '%s': %s, blacklisting\n", texName.c_str(), error.c_str());
- m_texBlacklist.insert(texName);
- return Texture(); // invalid texture
- }
+ CImage img;
+ if (! img.Load(m_app->GetDataFilePath(DIR_TEXTURE, texName)))
+ {
+ std::string error = img.GetError();
+ GetLogger()->Error("Couldn't load texture '%s': %s, blacklisting\n", texName.c_str(), error.c_str());
+ m_texBlacklist.insert(texName);
+ return Texture(); // invalid texture
+ }
- Texture tex = m_device->CreateTexture(&img, params);
+ tex = m_device->CreateTexture(&img, params);
+ }
+ else
+ {
+ tex = m_device->CreateTexture(image, params);
+ }
if (! tex.Valid())
{
@@ -2119,6 +2120,12 @@ Texture CEngine::LoadTexture(const std::string& name)
return LoadTexture(name, m_defaultTexParams);
}
+Texture CEngine::LoadTexture(const std::string& name, CImage* image)
+{
+ Texture tex = CreateTexture(name, m_defaultTexParams, image);
+ return tex;
+}
+
Texture CEngine::LoadTexture(const std::string& name, const TextureCreateParams& params)
{
if (m_texBlacklist.find(name) != m_texBlacklist.end())
@@ -2200,6 +2207,146 @@ bool CEngine::LoadAllTextures()
return ok;
}
+bool IsExcludeColor(Math::Point *exclude, int x, int y)
+{
+ int i = 0;
+ while ( exclude[i+0].x != 0.0f || exclude[i+0].y != 0.0f ||
+ exclude[i+1].y != 0.0f || exclude[i+1].y != 0.0f )
+ {
+ if ( x >= static_cast<int>(exclude[i+0].x*256.0f) &&
+ x < static_cast<int>(exclude[i+1].x*256.0f) &&
+ y >= static_cast<int>(exclude[i+0].y*256.0f) &&
+ y < static_cast<int>(exclude[i+1].y*256.0f) ) return true; // exclude
+
+ i += 2;
+ }
+
+ return false; // point to include
+}
+
+
+bool CEngine::ChangeTextureColor(const std::string& texName,
+ Color colorRef1, Color colorNew1,
+ Color colorRef2, Color colorNew2,
+ float tolerance1, float tolerance2,
+ Math::Point ts, Math::Point ti,
+ Math::Point *exclude, float shift, bool hsv)
+{
+ if ( colorRef1.r == colorNew1.r &&
+ colorRef1.g == colorNew1.g &&
+ colorRef1.b == colorNew1.b &&
+ colorRef2.r == colorNew2.r &&
+ colorRef2.g == colorNew2.g &&
+ colorRef2.b == colorNew2.b ) return true;
+
+
+ DeleteTexture(texName);
+
+
+ CImage img;
+ if (! img.Load(m_app->GetDataFilePath(DIR_TEXTURE, texName)))
+ {
+ std::string error = img.GetError();
+ GetLogger()->Error("Couldn't load texture '%s': %s, blacklisting\n", texName.c_str(), error.c_str());
+ m_texBlacklist.insert(texName);
+ return false;
+ }
+
+
+ int dx = img.GetSize().x;
+ int dy = img.GetSize().x;
+
+ int sx = static_cast<int>(ts.x*dx);
+ int sy = static_cast<int>(ts.y*dy);
+
+ int ex = static_cast<int>(ti.x*dx);
+ int ey = static_cast<int>(ti.y*dy);
+
+ ColorHSV cr1 = RGB2HSV(colorRef1);
+ ColorHSV cn1 = RGB2HSV(colorNew1);
+ ColorHSV cr2 = RGB2HSV(colorRef2);
+ ColorHSV cn2 = RGB2HSV(colorNew2);
+
+ for (int y = sy; y < ey; y++)
+ {
+ for (int x = sx; x < ex; x++)
+ {
+ if (exclude != nullptr && IsExcludeColor(exclude, x,y) ) continue;
+
+ Color color = img.GetPixel(Math::IntPoint(x, y));
+
+ if (hsv)
+ {
+ ColorHSV c = RGB2HSV(color);
+ if (c.s > 0.01f && fabs(c.h - cr1.h) < tolerance1)
+ {
+ c.h += cn1.h - cr1.h;
+ c.s += cn1.s - cr1.s;
+ c.v += cn1.v - cr1.v;
+ if (c.h < 0.0f) c.h -= 1.0f;
+ if (c.h > 1.0f) c.h += 1.0f;
+ color = HSV2RGB(c);
+ color.r += shift;
+ color.g += shift;
+ color.b += shift;
+ img.SetPixel(Math::IntPoint(x, y), color);
+ }
+ else if (tolerance2 != -1.0f &&
+ c.s > 0.01f && fabs(c.h - cr2.h) < tolerance2)
+ {
+ c.h += cn2.h - cr2.h;
+ c.s += cn2.s - cr2.s;
+ c.v += cn2.v - cr2.v;
+ if (c.h < 0.0f) c.h -= 1.0f;
+ if (c.h > 1.0f) c.h += 1.0f;
+ color = HSV2RGB(c);
+ color.r += shift;
+ color.g += shift;
+ color.b += shift;
+ img.SetPixel(Math::IntPoint(x, y), color);
+ }
+ }
+ else
+ {
+ if ( fabs(color.r - colorRef1.r) +
+ fabs(color.g - colorRef1.g) +
+ fabs(color.b - colorRef1.b) < tolerance1 * 3.0f)
+ {
+ color.r = colorNew1.r + color.r - colorRef1.r + shift;
+ color.g = colorNew1.g + color.g - colorRef1.g + shift;
+ color.b = colorNew1.b + color.b - colorRef1.b + shift;
+ img.SetPixel(Math::IntPoint(x, y), color);
+ }
+ else if (tolerance2 != -1 &&
+ fabs(color.r - colorRef2.r) +
+ fabs(color.g - colorRef2.g) +
+ fabs(color.b - colorRef2.b) < tolerance2 * 3.0f)
+ {
+ color.r = colorNew2.r + color.r - colorRef2.r + shift;
+ color.g = colorNew2.g + color.g - colorRef2.g + shift;
+ color.b = colorNew2.b + color.b - colorRef2.b + shift;
+ img.SetPixel(Math::IntPoint(x, y), color);
+ }
+ }
+ }
+ }
+
+
+ Texture tex = m_device->CreateTexture(&img, m_defaultTexParams);
+
+ if (! tex.Valid())
+ {
+ GetLogger()->Error("Couldn't load texture '%s', blacklisting\n", texName.c_str());
+ m_texBlacklist.insert(texName);
+ return false;
+ }
+
+ m_texNameMap[texName] = tex;
+ m_revTexNameMap[tex] = texName;
+
+ return true;
+}
+
void CEngine::DeleteTexture(const std::string& texName)
{
auto it = m_texNameMap.find(texName);
@@ -2348,11 +2495,6 @@ bool CEngine::GetFog()
return m_fog;
}
-bool CEngine::GetStateColor()
-{
- return m_stateColor;
-}
-
void CEngine::SetSecondTexture(int texNum)
{
m_secondTexNum = texNum;
@@ -2964,18 +3106,8 @@ void CEngine::Draw3DScene()
if (transparent)
{
- int tState = 0;
- Color tColor;
- if (m_stateColor)
- {
- tState = ENG_RSTATE_TTEXTURE_BLACK | ENG_RSTATE_2FACE;
- tColor = Color(68.0f / 255.0f, 68.0f / 255.0f, 68.0f / 255.0f, 68.0f / 255.0f);
- }
- else
- {
- tState = ENG_RSTATE_TCOLOR_BLACK;
- tColor = Color(136.0f / 255.0f, 136.0f / 255.0f, 136.0f / 255.0f, 136.0f / 255.0f);
- }
+ int tState = ENG_RSTATE_TTEXTURE_BLACK | ENG_RSTATE_2FACE;
+ Color tColor = Color(68.0f / 255.0f, 68.0f / 255.0f, 68.0f / 255.0f, 68.0f / 255.0f);
for (int l1 = 0; l1 < static_cast<int>( m_objectTree.size() ); l1++)
{
@@ -3551,8 +3683,6 @@ void CEngine::DrawForegroundImage()
// Status: PART_TESTED
void CEngine::DrawOverColor()
{
- if (! m_stateColor) return;
-
// TODO: fuzzy compare?
if ( (m_overColor == Color(0.0f, 0.0f, 0.0f, 0.0f) && m_overMode == ENG_RSTATE_TCOLOR_BLACK) ||
(m_overColor == Color(1.0f, 1.0f, 1.0f, 1.0f) && m_overMode == ENG_RSTATE_TCOLOR_WHITE) ) return;
diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h
index 6363fd3..14a40db 100644
--- a/src/graphics/engine/engine.h
+++ b/src/graphics/engine/engine.h
@@ -48,6 +48,7 @@ class CApplication;
class CInstanceManager;
class CObject;
class CSoundInterface;
+class CImage;
// Graphics module namespace
@@ -890,12 +891,23 @@ public:
const Math::Vector& upVec, float eyeDistance);
//! Loads texture, creating it if not already present
- Texture LoadTexture(const std::string& name);
+ Texture LoadTexture(const std::string& name);
+ //! Loads texture from existing image
+ Texture LoadTexture(const std::string& name, CImage* image);
//! Loads texture, creating it with given params if not already present
- Texture LoadTexture(const std::string& name, const TextureCreateParams& params);
+ Texture LoadTexture(const std::string& name, const TextureCreateParams& params);
//! Loads all necessary textures
bool LoadAllTextures();
+ //! Changes colors in a texture
+ bool ChangeTextureColor(const std::string& texName,
+ Color colorRef1, Color colorNew1,
+ Color colorRef2, Color colorNew2,
+ float tolerance1, float tolerance2,
+ Math::Point ts, Math::Point ti,
+ Math::Point *exclude = nullptr,
+ float shift = 0.0f, bool hsv = false);
+
//! Sets texture for given stage; if not present in cache, the texture is loaded
/** If loading fails, returns false. */
bool SetTexture(const std::string& name, int stage = 0);
@@ -973,19 +985,19 @@ public:
//@{
//! Ambient color management
void SetAmbientColor(const Color& color, int rank = 0);
- Color GetAmbientColor(int rank = 0);
+ Color GetAmbientColor(int rank = 0);
//@}
//@{
//! Color management under water
void SetWaterAddColor(const Color& color);
- Color GetWaterAddColor();
+ Color GetWaterAddColor();
//@}
//@{
//! Management of the fog color
void SetFogColor(const Color& color, int rank = 0);
- Color GetFogColor(int rank = 0);
+ Color GetFogColor(int rank = 0);
//@}
//@{
@@ -1188,7 +1200,7 @@ protected:
const Material& mat, int state);
//! Create texture and add it to cache
- Texture CreateTexture(const std::string &texName, const TextureCreateParams &params);
+ Texture CreateTexture(const std::string &texName, const TextureCreateParams &params, CImage* image = nullptr);
//! Tests whether the given object is visible
bool IsVisible(int objRank);
@@ -1291,8 +1303,6 @@ protected:
int m_statisticTriangle;
bool m_updateGeometry;
int m_alphaMode;
- bool m_stateColor;
- bool m_forceStateColor;
bool m_groundSpotVisible;
bool m_shadowVisible;
bool m_dirty;