From a8554cfae3358af6b909c45ba9dc9bdfc020bdfb Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Sat, 29 Sep 2012 23:37:38 +0200 Subject: Texture coloring --- src/graphics/engine/engine.cpp | 142 ++++++++++++++++++++++++++++++++++++++++- src/graphics/engine/engine.h | 18 ++++-- src/object/robotmain.cpp | 32 +++++----- 3 files changed, 169 insertions(+), 23 deletions(-) diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index c748605..b4ad962 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -2082,8 +2082,6 @@ 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? - CImage img; if (! img.Load(m_app->GetDataFilePath(DIR_TEXTURE, texName))) { @@ -2194,6 +2192,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(exclude[i+0].x*256.0f) && + x < static_cast(exclude[i+1].x*256.0f) && + y >= static_cast(exclude[i+0].y*256.0f) && + y < static_cast(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(ts.x*dx); + int sy = static_cast(ts.y*dy); + + int ex = static_cast(ti.x*dx); + int ey = static_cast(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); diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index 700903f..cbe5d04 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -890,12 +890,20 @@ 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, 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(); + 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 +981,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); //@} //@{ diff --git a/src/object/robotmain.cpp b/src/object/robotmain.cpp index 327e73f..dfb92d4 100644 --- a/src/object/robotmain.cpp +++ b/src/object/robotmain.cpp @@ -4905,7 +4905,7 @@ void CRobotMain::ChangeColor() exclu[3] = Math::Point(256.0f/256.0f, 256.0f/256.0f); // SatCom screen exclu[4] = Math::Point(0.0f, 0.0f); exclu[5] = Math::Point(0.0f, 0.0f); // terminator - // TODO: m_engine->ChangeColor("human.png", colorRef1, colorNew1, colorRef2, colorNew2, 0.30f, 0.01f, ts, ti, exclu); + m_engine->ChangeTextureColor("human.png", colorRef1, colorNew1, colorRef2, colorNew2, 0.30f, 0.01f, ts, ti, exclu); float tolerance; @@ -4952,7 +4952,7 @@ void CRobotMain::ChangeColor() exclu[1] = Math::Point(153.0f/256.0f, 79.0f/166.0f); // blue canister exclu[2] = Math::Point(0.0f, 0.0f); exclu[3] = Math::Point(0.0f, 0.0f); // terminator - // TODO: m_engine->ChangeColor(name, colorRef1, colorNew1, colorRef2, colorNew2, tolerance, 0.00f, ts, ti, exclu); + m_engine->ChangeTextureColor(name, colorRef1, colorNew1, colorRef2, colorNew2, tolerance, 0.00f, ts, ti, exclu); colorRef2.r = 0.0f; colorRef2.g = 0.0f; @@ -4961,19 +4961,19 @@ void CRobotMain::ChangeColor() colorNew2.g = 0.0f; colorNew2.b = 0.0f; - // TODO: m_engine->ChangeColor("base1.png", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true); - // TODO: m_engine->ChangeColor("convert.png", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true); - // TODO: m_engine->ChangeColor("derrick.png", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true); - // TODO: m_engine->ChangeColor("factory.png", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true); - // TODO: m_engine->ChangeColor("lemt.png", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true); - // TODO: m_engine->ChangeColor("roller.png", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true); - // TODO: m_engine->ChangeColor("search.png", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true); + m_engine->ChangeTextureColor("base1.png", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true); + m_engine->ChangeTextureColor("convert.png", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true); + m_engine->ChangeTextureColor("derrick.png", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true); + m_engine->ChangeTextureColor("factory.png", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true); + m_engine->ChangeTextureColor("lemt.png", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true); + m_engine->ChangeTextureColor("roller.png", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true); + m_engine->ChangeTextureColor("search.png", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, 0, 0, true); exclu[0] = Math::Point( 0.0f/256.0f, 160.0f/256.0f); exclu[1] = Math::Point(256.0f/256.0f, 256.0f/256.0f); // pencils exclu[2] = Math::Point(0.0f, 0.0f); exclu[3] = Math::Point(0.0f, 0.0f); // terminator - // TODO: m_engine->ChangeColor("drawer.png", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, exclu, 0, true); + m_engine->ChangeTextureColor("drawer.png", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, exclu, 0, true); exclu[0] = Math::Point(237.0f/256.0f, 176.0f/256.0f); exclu[1] = Math::Point(256.0f/256.0f, 220.0f/256.0f); // blue canister @@ -4981,26 +4981,26 @@ void CRobotMain::ChangeColor() exclu[3] = Math::Point(130.0f/256.0f, 214.0f/256.0f); // safe location exclu[4] = Math::Point(0.0f, 0.0f); exclu[5] = Math::Point(0.0f, 0.0f); // terminator - // TODO: m_engine->ChangeColor("subm.png", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, exclu, 0, true); + m_engine->ChangeTextureColor("subm.png", m_colorRefBot, m_colorNewBot, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, exclu, 0, true); exclu[0] = Math::Point(128.0f/256.0f, 160.0f/256.0f); exclu[1] = Math::Point(256.0f/256.0f, 256.0f/256.0f); // SatCom exclu[2] = Math::Point(0.0f, 0.0f); exclu[3] = Math::Point(0.0f, 0.0f); // terminator - // TODO: m_engine->ChangeColor("ant.png", m_colorRefAlien, m_colorNewAlien, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti, exclu); - // TODO: m_engine->ChangeColor("mother.png", m_colorRefAlien, m_colorNewAlien, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti); + m_engine->ChangeTextureColor("ant.png", m_colorRefAlien, m_colorNewAlien, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti, exclu); + m_engine->ChangeTextureColor("mother.png", m_colorRefAlien, m_colorNewAlien, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti); - // TODO: m_engine->ChangeColor("plant.png", m_colorRefGreen, m_colorNewGreen, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti); + m_engine->ChangeTextureColor("plant.png", m_colorRefGreen, m_colorNewGreen, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti); // PARTIPLOUF0 and PARTIDROP : ts = Math::Point(0.500f, 0.500f); ti = Math::Point(0.875f, 0.750f); - // TODO: m_engine->ChangeColor("effect00.png", m_colorRefWater, m_colorNewWater, colorRef2, colorNew2, 0.20f, -1.0f, ts, ti, 0, m_colorShiftWater, true); + m_engine->ChangeTextureColor("effect00.png", m_colorRefWater, m_colorNewWater, colorRef2, colorNew2, 0.20f, -1.0f, ts, ti, 0, m_colorShiftWater, true); // PARTIFLIC : ts = Math::Point(0.00f, 0.75f); ti = Math::Point(0.25f, 1.00f); - // TODO: m_engine->ChangeColor("effect02.png", m_colorRefWater, m_colorNewWater, colorRef2, colorNew2, 0.20f, -1.0f, ts, ti, 0, m_colorShiftWater, true); + m_engine->ChangeTextureColor("effect02.png", m_colorRefWater, m_colorNewWater, colorRef2, colorNew2, 0.20f, -1.0f, ts, ti, 0, m_colorShiftWater, true); } //! Updates the number of unnecessary objects -- cgit v1.2.3-1-g7c22