From 7d9badb542adb1cd505a005d1832efbe8133e483 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Kapu=C5=9Bci=C5=84ski?= Date: Wed, 2 Feb 2022 18:13:21 +0100 Subject: [PATCH] Added UV transform and rewritten animated texture mapping code to use it --- src/graphics/core/renderers.h | 3 + src/graphics/engine/engine.cpp | 179 +++--------------- src/graphics/engine/engine.h | 30 +-- src/graphics/opengl/gl33objectrenderer.cpp | 10 + src/graphics/opengl/gl33objectrenderer.h | 6 + .../opengl/shaders/gl33/object_vs.glsl | 5 +- src/object/auto/autoportico.cpp | 16 +- src/object/motion/motionvehicle.cpp | 26 +-- src/object/old_object.cpp | 9 +- 9 files changed, 79 insertions(+), 205 deletions(-) diff --git a/src/graphics/core/renderers.h b/src/graphics/core/renderers.h index 05432fed..da06cab7 100644 --- a/src/graphics/core/renderers.h +++ b/src/graphics/core/renderers.h @@ -174,6 +174,9 @@ public: //! Sets transparency mode virtual void SetTransparency(TransparencyMode mode) = 0; + //! Sets UV transform + virtual void SetUVTransform(const glm::vec2& offset, const glm::vec2& scale) = 0; + virtual void SetPrimaryTextureEnabled(bool enabled) = 0; //! Sets triplanar mode virtual void SetTriplanarMode(bool enabled) = 0; diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index 1bbd73f1..67f7f06d 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -640,7 +640,7 @@ EngineBaseObjDataTier& CEngine::AddLevel3(EngineBaseObjTexTier& p3, EngineTriang return p3.next[i]; } - p3.next.push_back(EngineBaseObjDataTier(type, state)); + p3.next.push_back(EngineBaseObjDataTier{ type, state }); return p3.next.back(); } @@ -1162,168 +1162,35 @@ void CEngine::ChangeSecondTexture(int objRank, const std::string& tex2Name) } } -void CEngine::ChangeTextureMapping(int objRank, int state, - const std::string& tex1Name, const std::string& tex2Name, - EngineTextureMapping mode, - float au, float bu, float av, float bv) +void CEngine::SetUVTransform(int objRank, int state, const glm::vec2& offset, const glm::vec2& scale) { - assert(objRank >= 0 && objRank < static_cast( m_objects.size() )); + assert(objRank >= 0 && objRank < static_cast(m_objects.size())); - EngineBaseObjDataTier* p4 = FindTriangles(objRank, state, tex1Name, tex2Name); - if (p4 == nullptr) + int baseObjRank = m_objects[objRank].baseObjRank; + if (baseObjRank == -1) return; - int nb = p4->vertices.size(); + assert(baseObjRank >= 0 && baseObjRank < static_cast(m_baseObjects.size())); - if (mode == EngineTextureMapping::X) - { - for (int i = 0; i < nb; i++) - { - p4->vertices[i].uv.x = p4->vertices[i].position.z * au + bu; - p4->vertices[i].uv.y = p4->vertices[i].position.y * av + bv; - } - } - else if (mode == EngineTextureMapping::Y) - { - for (int i = 0; i < nb; i++) - { - p4->vertices[i].uv.x = p4->vertices[i].position.x * au + bu; - p4->vertices[i].uv.y = p4->vertices[i].position.z * av + bv; - } - } - else if (mode == EngineTextureMapping::Z) - { - for (int i = 0; i < nb; i++) - { - p4->vertices[i].uv.x = p4->vertices[i].position.x * au + bu; - p4->vertices[i].uv.y = p4->vertices[i].position.y * av + bv; - } - } - else if (mode == EngineTextureMapping::ONE_X) - { - for (int i = 0; i < nb; i++) - { - p4->vertices[i].uv.x = p4->vertices[i].position.x * au + bu; - } - } - else if (mode == EngineTextureMapping::ONE_Y) - { - for (int i = 0; i < nb; i++) - { - p4->vertices[i].uv.y = p4->vertices[i].position.y * au + bu; - } - } - else if (mode == EngineTextureMapping::ONE_Z) - { - for (int i = 0; i < nb; i++) - { - p4->vertices[i].uv.x = p4->vertices[i].position.z * au + bu; - } - } + EngineBaseObject& p1 = m_baseObjects[baseObjRank]; - UpdateStaticBuffer(*p4); + for (size_t l2 = 0; l2 < p1.next.size(); l2++) + { + EngineBaseObjTexTier& p2 = p1.next[l2]; + + for (size_t l3 = 0; l3 < p2.next.size(); l3++) + { + EngineBaseObjDataTier& p3 = p2.next[l3]; + + if (p3.state & state) + { + p3.uvOffset = offset; + p3.uvScale = scale; + } + } + } } -void CEngine::TrackTextureMapping(int objRank, int state, - const std::string& tex1Name, const std::string& tex2Name, - EngineTextureMapping mode, - float pos, float factor, float tl, float ts, float tt) -{ - assert(objRank >= 0 && objRank < static_cast( m_objects.size() )); - - EngineBaseObjDataTier* p4 = FindTriangles(objRank, state, tex1Name, tex2Name); - if (p4 == nullptr) - return; - - int tNum = p4->vertices.size(); - if (tNum < 12 || tNum % 6 != 0) - return; - - std::vector& vs = p4->vertices; - - while (pos < 0.0f) - pos += 1.0f; // never negative! - - glm::vec3 current{ 0, 0, 0 }; - - for (int i = 0; i < 6; i++) - { - for (int j = 0; j < 6; j++) - { - if (Math::IsEqual(vs[i].position.x, vs[j+6].position.x) && - Math::IsEqual(vs[i].position.y, vs[j+6].position.y)) - { - current.x = vs[i].position.x; // position end link - current.y = vs[i].position.y; - break; - } - } - } - - float ps = 0.0f; // start position on the periphery - float pe = 0.0f; - int is[6] = { 0 }, ie[6] = { 0 }; - - int tBase = 0; - for (int ti = 0; ti < tNum / 6; ti++) - { - int s = 0; - int e = 0; - - for (int i = 0; i < 6; i++) - { - if (Math::IsEqual(vs[tBase + i].position.x, current.x, 0.0001f) && - Math::IsEqual(vs[tBase + i].position.y, current.y, 0.0001f)) - { - ie[e++] = i; - } - else - { - is[s++] = i; - } - } - if (s == 3 && e == 3) - { - glm::vec2 endPosition{}; - endPosition.x = vs[tBase + is[0]].position.x - vs[tBase + ie[0]].position.x; - endPosition.y = vs[tBase + is[0]].position.y - vs[tBase + ie[0]].position.y; - - pe = ps + glm::length(endPosition) / factor; // end position on the periphery - - float pps = ps + pos; - float ppe = pe + pos; - int offset = static_cast(pps); - ppe -= offset; - pps -= offset; - - for (int i = 0; i < 3; i++) - { - vs[tBase + is[i]].uv.x = ((pps * tl) + ts) / tt; - vs[tBase + ie[i]].uv.x = ((ppe * tl) + ts) / tt; - } - } - - if (ti >= (tNum / 6) - 1) - break; - - for (int i = 0; i < 6; i++) - { - if (!Math::IsEqual(vs[tBase + i+6].position.x, current.x, 0.0001f) || - !Math::IsEqual(vs[tBase + i+6].position.y, current.y, 0.0001f)) - { - current.x = vs[tBase + i+6].position.x; // end next link - current.y = vs[tBase + i+6].position.y; - break; - } - } - ps = pe; // following start position on the periphery - tBase += 6; - } - - UpdateStaticBuffer(*p4); -} - - void CEngine::CreateShadowSpot(int objRank) { assert(objRank >= 0 && objRank < static_cast( m_objects.size() )); @@ -3570,6 +3437,7 @@ void CEngine::Draw3DScene() objectRenderer->SetDirty(dirty); objectRenderer->SetColor({ 1.0f, 1.0f, 1.0f, 1.0f }); objectRenderer->SetCullMode((p3.state& ENG_RSTATE_2FACE) == 0); + objectRenderer->SetUVTransform(p3.uvOffset, p3.uvScale); objectRenderer->DrawObject(p3.buffer); } } @@ -3635,6 +3503,7 @@ void CEngine::Draw3DScene() float dirty = (p3.state & ENG_RSTATE_DUAL_BLACK) && m_dirty ? 1.0 : 0.0; objectRenderer->SetDirty(dirty); objectRenderer->SetColor(tColor); + objectRenderer->SetUVTransform(p3.uvOffset, p3.uvScale); objectRenderer->DrawObject(p3.buffer); } } diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index 86db73be..d71cbac8 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -189,19 +189,13 @@ enum EngineObjectType */ struct EngineBaseObjDataTier { - EngineTriangleType type; - int state; + EngineTriangleType type = EngineTriangleType::TRIANGLES; + int state = ENG_RSTATE_NORMAL; std::vector vertices; - CVertexBuffer* buffer; - bool updateStaticBuffer; - - inline EngineBaseObjDataTier(EngineTriangleType type = EngineTriangleType::TRIANGLES, - int state = ENG_RSTATE_NORMAL) - : type(type) - , state(state) - , buffer(nullptr) - , updateStaticBuffer(false) - {} + CVertexBuffer* buffer = nullptr; + bool updateStaticBuffer = false; + glm::vec2 uvOffset = { 0.0f, 0.0f }; + glm::vec2 uvScale = { 1.0f, 1.0f }; }; /** @@ -785,17 +779,7 @@ public: //! Changes the 2nd texure for given object void ChangeSecondTexture(int objRank, const std::string& tex2Name); - //! Changes (recalculates) texture mapping for given object - void ChangeTextureMapping(int objRank, int state, - const std::string& tex1Name, const std::string& tex2Name, - EngineTextureMapping mode, - float au, float bu, float av, float bv); - - //! Changes texture mapping for robot tracks - void TrackTextureMapping(int objRank, int state, - const std::string& tex1Name, const std::string& tex2Name, - EngineTextureMapping mode, - float pos, float factor, float tl, float ts, float tt); + void SetUVTransform(int objRank, int state, const glm::vec2& offset, const glm::vec2& scale); //! Detects the target object that is selected with the mouse /** Returns the rank of the object or -1. */ diff --git a/src/graphics/opengl/gl33objectrenderer.cpp b/src/graphics/opengl/gl33objectrenderer.cpp index d40daa07..76d60625 100644 --- a/src/graphics/opengl/gl33objectrenderer.cpp +++ b/src/graphics/opengl/gl33objectrenderer.cpp @@ -86,6 +86,8 @@ CGL33ObjectRenderer::CGL33ObjectRenderer(CGL33Device* device) m_triplanarScale = glGetUniformLocation(m_program, "uni_TriplanarScale"); m_dirty = glGetUniformLocation(m_program, "uni_Dirty"); m_alphaScissor = glGetUniformLocation(m_program, "uni_AlphaScissor"); + m_uvOffset = glGetUniformLocation(m_program, "uni_UVOffset"); + m_uvScale = glGetUniformLocation(m_program, "uni_UVScale"); m_shadowRegions = glGetUniformLocation(m_program, "uni_ShadowRegions"); @@ -174,6 +176,8 @@ void CGL33ObjectRenderer::CGL33ObjectRenderer::Begin() glEnable(GL_DEPTH_TEST); glDepthMask(GL_TRUE); + + SetUVTransform({ 0.0f, 0.0f }, { 1.0f, 1.0f }); } void CGL33ObjectRenderer::CGL33ObjectRenderer::End() @@ -349,6 +353,12 @@ void CGL33ObjectRenderer::SetTransparency(TransparencyMode mode) } } +void CGL33ObjectRenderer::SetUVTransform(const glm::vec2& offset, const glm::vec2& scale) +{ + glUniform2fv(m_uvOffset, 1, glm::value_ptr(offset)); + glUniform2fv(m_uvScale, 1, glm::value_ptr(scale)); +} + void CGL33ObjectRenderer::SetPrimaryTextureEnabled(bool enabled) { glUniform1f(m_primaryEnabled, enabled ? 1.0f : 0.0f); diff --git a/src/graphics/opengl/gl33objectrenderer.h b/src/graphics/opengl/gl33objectrenderer.h index 1a1e5223..df270bda 100644 --- a/src/graphics/opengl/gl33objectrenderer.h +++ b/src/graphics/opengl/gl33objectrenderer.h @@ -83,6 +83,10 @@ public: virtual void SetCullMode(bool enabled) override; //! Sets transparency mode virtual void SetTransparency(TransparencyMode mode) override; + + //! Sets UV transform + virtual void SetUVTransform(const glm::vec2& offset, const glm::vec2& scale) override; + virtual void SetPrimaryTextureEnabled(bool enabled) override; //! Sets triplanar mode @@ -119,6 +123,8 @@ private: GLint m_triplanarScale = -1; GLint m_dirty = -1; GLint m_alphaScissor = -1; + GLint m_uvOffset = -1; + GLint m_uvScale = -1; struct ShadowUniforms { diff --git a/src/graphics/opengl/shaders/gl33/object_vs.glsl b/src/graphics/opengl/shaders/gl33/object_vs.glsl index dcc9db65..b21d81a7 100644 --- a/src/graphics/opengl/shaders/gl33/object_vs.glsl +++ b/src/graphics/opengl/shaders/gl33/object_vs.glsl @@ -24,6 +24,9 @@ uniform mat4 uni_ViewMatrix; uniform mat4 uni_ModelMatrix; uniform mat3 uni_NormalMatrix; +uniform vec2 uni_UVOffset; +uniform vec2 uni_UVScale; + layout(location = 0) in vec4 in_VertexCoord; layout(location = 1) in vec3 in_Normal; layout(location = 2) in vec4 in_Color; @@ -49,7 +52,7 @@ void main() gl_Position = uni_ProjectionMatrix * eyeSpace; data.Color = in_Color; - data.TexCoord0 = in_TexCoord0; + data.TexCoord0 = in_TexCoord0 * uni_UVScale + uni_UVOffset; data.TexCoord1 = in_TexCoord1; data.Normal = mat3(uni_NormalMatrix) * in_Normal; data.VertexCoord = in_VertexCoord.xyz; diff --git a/src/object/auto/autoportico.cpp b/src/object/auto/autoportico.cpp index 130328b5..a3383284 100644 --- a/src/object/auto/autoportico.cpp +++ b/src/object/auto/autoportico.cpp @@ -395,14 +395,14 @@ void CAutoPortico::UpdateTrackMapping(float left, float right) { int rank = m_object->GetObjectRank(0); - std::string teamStr = StrUtils::ToString(m_object->GetTeam()); - if(m_object->GetTeam() == 0) teamStr = ""; + constexpr float scale = 0.25f / 8.0f; - m_engine->TrackTextureMapping(rank, Gfx::ENG_RSTATE_PART1, "objects/lemt.png"+teamStr, "", - Gfx::EngineTextureMapping::X, - right, 8.0f, 8.0f, 192.0f, 256.0f); + left = left - std::floor(left); + right = right - std::floor(right); - m_engine->TrackTextureMapping(rank, Gfx::ENG_RSTATE_PART2, "objects/lemt.png"+teamStr, "", - Gfx::EngineTextureMapping::X, - left, 8.0f, 8.0f, 192.0f, 256.0f); + m_engine->SetUVTransform(rank, Gfx::ENG_RSTATE_PART1, + { (1.0f - right) * scale, 0.0f }, { 1.0f, 1.0f }); + + m_engine->SetUVTransform(rank, Gfx::ENG_RSTATE_PART2, + { (1.0f - left) * scale, 0.0f }, { 1.0f, 1.0f }); } diff --git a/src/object/motion/motionvehicle.cpp b/src/object/motion/motionvehicle.cpp index c988df79..62773318 100644 --- a/src/object/motion/motionvehicle.cpp +++ b/src/object/motion/motionvehicle.cpp @@ -1984,25 +1984,25 @@ void CMotionVehicle::UpdateTrackMapping(float left, float right, ObjectType type std::string teamStr = StrUtils::ToString(m_object->GetTeam()); if(m_object->GetTeam() == 0) teamStr = ""; + constexpr float scale = 0.25f / 8.0f; + + left = left - std::floor(left); + right = right - std::floor(right); + if (type == OBJECT_MOBILEdr) { - m_engine->TrackTextureMapping(rRank, Gfx::ENG_RSTATE_PART1, "objects/drawer.png"+teamStr, "", - Gfx::EngineTextureMapping::X, - right, 1.0f, 8.0f, 192.0f, 256.0f); + m_engine->SetUVTransform(rRank, Gfx::ENG_RSTATE_PART1, + { (1.0f - right) * scale, 0.0f }, { 1.0f, 1.0f }); - m_engine->TrackTextureMapping(lRank, Gfx::ENG_RSTATE_PART2, "objects/drawer.png"+teamStr, "", - Gfx::EngineTextureMapping::X, - left, 1.0f, 8.0f, 192.0f, 256.0f); + m_engine->SetUVTransform(lRank, Gfx::ENG_RSTATE_PART2, + { (1.0f - left) * scale, 0.0f }, { 1.0f, 1.0f }); } else { - m_engine->TrackTextureMapping(rRank, Gfx::ENG_RSTATE_PART1, "objects/lemt.png"+teamStr, "", - Gfx::EngineTextureMapping::X, - right, 1.0f, 8.0f, 192.0f, 256.0f); + m_engine->SetUVTransform(rRank, Gfx::ENG_RSTATE_PART1, + { (1.0f - right) * scale, 0.0f }, { 1.0f, 1.0f }); - m_engine->TrackTextureMapping(lRank, Gfx::ENG_RSTATE_PART2, "objects/lemt.png"+teamStr, "", - Gfx::EngineTextureMapping::X, - left, 1.0f, 8.0f, 192.0f, 256.0f); + m_engine->SetUVTransform(lRank, Gfx::ENG_RSTATE_PART2, + { (1.0f - left) * scale, 0.0f }, { 1.0f, 1.0f }); } - } diff --git a/src/object/old_object.cpp b/src/object/old_object.cpp index 199cf422..03345b58 100644 --- a/src/object/old_object.cpp +++ b/src/object/old_object.cpp @@ -2120,7 +2120,7 @@ void COldObject::FlatParent() void COldObject::UpdateEnergyMapping() { - if (Math::IsEqual(GetEnergyLevel(), m_lastEnergy, 0.01f)) + if (m_lastEnergy == GetEnergyLevel()) return; m_lastEnergy = GetEnergyLevel(); @@ -2152,10 +2152,9 @@ void COldObject::UpdateEnergyMapping() std::string teamStr = StrUtils::ToString(GetTeam()); if(GetTeam() == 0) teamStr = ""; - m_engine->ChangeTextureMapping(m_objectPart[0].object, - Gfx::ENG_RSTATE_PART3, "objects/lemt.png"+teamStr, "", - Gfx::EngineTextureMapping::ONE_Y, - au, bu, 1.0f, 0.0f); + + m_engine->SetUVTransform(m_objectPart[0].object, Gfx::ENG_RSTATE_PART3, + { 0.0f, 0.25f * (GetEnergyLevel() - 1.0f) }, { 1.0f, 1.0f }); }