diff options
Diffstat (limited to 'src/graphics/engine')
-rw-r--r-- | src/graphics/engine/engine.cpp | 206 | ||||
-rw-r--r-- | src/graphics/engine/engine.h | 26 |
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 ¶ms); + Texture CreateTexture(const std::string &texName, const TextureCreateParams ¶ms, 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; |