From c3780091281174d7552b4200041c6fa85b4850ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Kapu=C5=9Bci=C5=84ski?= Date: Sun, 13 Feb 2022 00:03:46 +0100 Subject: [PATCH] Feature-breaking refactors * Partially filled Material structure, currently only base attributes * Removed recoloring of textures and team variants * Removed one base object tier in engine structures * Removed EngineRenderState * Rewritten some code to better coding style --- src/graphics/core/device.h | 14 +- src/graphics/core/material.h | 44 +- src/graphics/core/transparency.h | 8 + src/graphics/engine/engine.cpp | 616 ++++++++---------------- src/graphics/engine/engine.h | 129 +---- src/graphics/engine/oldmodelmanager.cpp | 6 +- src/graphics/engine/particle.cpp | 5 +- src/graphics/engine/terrain.cpp | 26 +- src/graphics/model/model_input.cpp | 52 +- src/graphics/model/model_io_structs.h | 2 - src/graphics/model/model_triangle.h | 34 +- src/level/robotmain.cpp | 34 +- src/object/auto/autoportico.cpp | 4 +- src/object/motion/motionvehicle.cpp | 8 +- src/object/old_object.cpp | 2 +- src/ui/controls/control.cpp | 1 - 16 files changed, 346 insertions(+), 639 deletions(-) diff --git a/src/graphics/core/device.h b/src/graphics/core/device.h index 5bcbe5d5..987b054f 100644 --- a/src/graphics/core/device.h +++ b/src/graphics/core/device.h @@ -58,6 +58,8 @@ struct Vertex; struct VertexCol; struct Vertex3D; +enum class CullFace : unsigned char; + /** * \struct DeviceConfig * \brief General config for graphics device @@ -142,18 +144,6 @@ enum CompFunc COMP_FUNC_ALWAYS }; -/** - * \enum CullFace - * \brief Specifies which faces to cull while rendering polygons - */ -enum class CullFace : unsigned char -{ - NONE, - BACK, - FRONT, - BOTH, -}; - /** * \enum FillMode * \brief Polygon fill mode diff --git a/src/graphics/core/material.h b/src/graphics/core/material.h index 18c65e07..687adc7b 100644 --- a/src/graphics/core/material.h +++ b/src/graphics/core/material.h @@ -26,16 +26,58 @@ #include "graphics/core/color.h" +#include "graphics/core/transparency.h" // Graphics module namespace namespace Gfx { +/** + * \enum CullFace + * \brief Specifies which faces to cull while rendering polygons + */ +enum class CullFace : unsigned char +{ + NONE, + BACK, + FRONT, + BOTH, +}; + //! Remains of the legacy material structure, to be reused struct Material { - + // Albedo + Color albedoColor = Color{ 1.0f, 1.0f, 1.0f, 1.0f }; + std::string albedoTexture = ""; + // Dirt + bool variableDetail = false; + std::string detailTexture = ""; + // Alpha mode + AlphaMode alphaMode = AlphaMode::OPAQUE; + float alphaThreshold = 0.0; + // Cull face + CullFace cullFace = CullFace::BACK; + // Special tag + std::string tag = ""; + + bool operator==(const Material& other) const + { + return albedoColor == other.albedoColor + && albedoTexture == other.albedoTexture + && variableDetail == other.variableDetail + && detailTexture == other.detailTexture + && alphaMode == other.alphaMode + && alphaThreshold == other.alphaThreshold + && cullFace == other.cullFace + && tag == other.tag; + } + + bool operator!=(const Material& other) const + { + return !operator==(other); + } }; } // namespace Gfx diff --git a/src/graphics/core/transparency.h b/src/graphics/core/transparency.h index 3e5688b3..afc847c1 100644 --- a/src/graphics/core/transparency.h +++ b/src/graphics/core/transparency.h @@ -37,4 +37,12 @@ enum class TransparencyMode : unsigned char WHITE, }; +//! Alpha transparency mode +enum class AlphaMode : unsigned char +{ + OPAQUE, // opaque material + MASK, // alpha scissor with threshold + BLEND, // alpha blending +}; + } diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index 95c88857..37f57da2 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -619,51 +619,40 @@ void CEngine::SetTimerDisplay(const std::string& text) Object management *******************************************************/ -EngineBaseObjTexTier& CEngine::AddLevel2(EngineBaseObject& p1, const std::string& tex1Name, const std::string& tex2Name) +EngineBaseObjDataTier& CEngine::AddLevel(EngineBaseObject& p3, EngineTriangleType type, const Material& material) { - for (int i = 0; i < static_cast( p1.next.size() ); i++) + for (size_t i = 0; i < p3.next.size(); i++) { - if (p1.next[i].tex1Name == tex1Name && p1.next[i].tex2Name == tex2Name) - return p1.next[i]; - } - - p1.next.push_back(EngineBaseObjTexTier(tex1Name, tex2Name)); - return p1.next.back(); -} - -EngineBaseObjDataTier& CEngine::AddLevel3(EngineBaseObjTexTier& p3, EngineTriangleType type, int state) -{ - for (int i = 0; i < static_cast( p3.next.size() ); i++) - { - if ( (p3.next[i].type == type) && (p3.next[i].state == state) ) + if ( (p3.next[i].type == type) && (p3.next[i].material == material) ) return p3.next[i]; } - p3.next.push_back(EngineBaseObjDataTier{ type, state }); + p3.next.push_back(EngineBaseObjDataTier{ type, material }); return p3.next.back(); } int CEngine::CreateBaseObject() { - int baseObjRank = 0; - for ( ; baseObjRank < static_cast( m_baseObjects.size() ); baseObjRank++) + size_t baseObjRank = 0; + + for (; baseObjRank < m_baseObjects.size(); baseObjRank++) { - if (! m_baseObjects[baseObjRank].used) + if (!m_baseObjects[baseObjRank].used) { - m_baseObjects[baseObjRank].LoadDefault(); + m_baseObjects[baseObjRank] = {}; break; } } - if (baseObjRank == static_cast( m_baseObjects.size() )) + if (baseObjRank == m_baseObjects.size()) m_baseObjects.push_back(EngineBaseObject()); else - m_baseObjects[baseObjRank].LoadDefault(); + m_baseObjects[baseObjRank] = {}; m_baseObjects[baseObjRank].used = true; - return baseObjRank; + return static_cast(baseObjRank); } void CEngine::DeleteBaseObject(int baseObjRank) @@ -675,41 +664,27 @@ void CEngine::DeleteBaseObject(int baseObjRank) if (! p1.used) return; - for (int l2 = 0; l2 < static_cast( p1.next.size() ); l2++) + for (auto& data : p1.next) { - EngineBaseObjTexTier& p2 = p1.next[l2]; - - for (int l3 = 0; l3 < static_cast( p2.next.size() ); l3++) - { - EngineBaseObjDataTier& p3 = p2.next[l3]; - m_device->DestroyVertexBuffer(p3.buffer); - p3.buffer = nullptr; - } + m_device->DestroyVertexBuffer(data.buffer); + data.buffer = nullptr; } p1.next.clear(); - p1.used = false; } void CEngine::DeleteAllBaseObjects() { - for (int baseObjRank = 0; baseObjRank < static_cast( m_baseObjects.size() ); baseObjRank++) + for (auto& object : m_baseObjects) { - EngineBaseObject& p1 = m_baseObjects[baseObjRank]; - if (! p1.used) + if (!object.used) continue; - for (int l2 = 0; l2 < static_cast( p1.next.size() ); l2++) + for (auto& data : object.next) { - EngineBaseObjTexTier& p2 = p1.next[l2]; - - for (int l3 = 0; l3 < static_cast( p2.next.size() ); l3++) - { - EngineBaseObjDataTier& p3 = p2.next[l3]; - m_device->DestroyVertexBuffer(p3.buffer); - p3.buffer = nullptr; - } + m_device->DestroyVertexBuffer(data.buffer); + data.buffer = nullptr; } } @@ -728,33 +703,33 @@ void CEngine::CopyBaseObject(int sourceBaseObjRank, int destBaseObjRank) if (! p1.used) return; - for (int l2 = 0; l2 < static_cast( p1.next.size() ); l2++) + for (auto& data : p1.next) { - EngineBaseObjTexTier& p2 = p1.next[l2]; - - for (int l3 = 0; l3 < static_cast( p2.next.size() ); l3++) - { - EngineBaseObjDataTier& p3 = p2.next[l3]; - p3.buffer = nullptr; - } + data.buffer = nullptr; + data.updateStaticBuffer = true; } + + m_updateStaticBuffers = true; } void CEngine::AddBaseObjTriangles(int baseObjRank, const std::vector& vertices, - int state, std::string tex1Name, std::string tex2Name) + const Material& material, EngineTriangleType type) { assert(baseObjRank >= 0 && baseObjRank < static_cast( m_baseObjects.size() )); EngineBaseObject& p1 = m_baseObjects[baseObjRank]; - EngineBaseObjTexTier& p2 = AddLevel2(p1, tex1Name, tex2Name); - EngineBaseObjDataTier& p3 = AddLevel3(p2, EngineTriangleType::TRIANGLES, state); + EngineBaseObjDataTier& p3 = AddLevel(p1, type, material); p3.vertices.insert(p3.vertices.end(), vertices.begin(), vertices.end()); + if (p3.buffer) + m_device->DestroyVertexBuffer(p3.buffer); + + p3.buffer = nullptr; p3.updateStaticBuffer = true; m_updateStaticBuffers = true; - for (int i = 0; i < static_cast( vertices.size() ); i++) + for (size_t i = 0; i < vertices.size(); i++) { p1.bboxMin.x = Math::Min(vertices[i].position.x, p1.bboxMin.x); p1.bboxMin.y = Math::Min(vertices[i].position.y, p1.bboxMin.y); @@ -769,46 +744,6 @@ void CEngine::AddBaseObjTriangles(int baseObjRank, const std::vector& p1.totalTriangles += vertices.size() / 3; } -void CEngine::AddBaseObjQuick(int baseObjRank, const EngineBaseObjDataTier& buffer, - std::string tex1Name, std::string tex2Name, - bool globalUpdate) -{ - assert(baseObjRank >= 0 && baseObjRank < static_cast( m_baseObjects.size() )); - - EngineBaseObject& p1 = m_baseObjects[baseObjRank]; - EngineBaseObjTexTier& p2 = AddLevel2(p1, tex1Name, tex2Name); - - p2.next.push_back(buffer); - - EngineBaseObjDataTier& p3 = p2.next.back(); - - UpdateStaticBuffer(p3); - - if (globalUpdate) - { - m_updateGeometry = true; - } - else - { - for (int i = 0; i < static_cast( p3.vertices.size() ); i++) - { - p1.bboxMin.x = Math::Min(p3.vertices[i].position.x, p1.bboxMin.x); - p1.bboxMin.y = Math::Min(p3.vertices[i].position.y, p1.bboxMin.y); - p1.bboxMin.z = Math::Min(p3.vertices[i].position.z, p1.bboxMin.z); - p1.bboxMax.x = Math::Max(p3.vertices[i].position.x, p1.bboxMax.x); - p1.bboxMax.y = Math::Max(p3.vertices[i].position.y, p1.bboxMax.y); - p1.bboxMax.z = Math::Max(p3.vertices[i].position.z, p1.bboxMax.z); - } - - p1.boundingSphere = Math::BoundingSphereForBox(p1.bboxMin, p1.bboxMax); - } - - if (p3.type == EngineTriangleType::TRIANGLES) - p1.totalTriangles += p3.vertices.size() / 3; - else if (p3.type == EngineTriangleType::SURFACE) - p1.totalTriangles += p3.vertices.size() - 2; -} - void CEngine::DebugObject(int objRank) { assert(objRank >= 0 && objRank < static_cast( m_objects.size() )); @@ -859,9 +794,10 @@ void CEngine::DebugObject(int objRank) for (int l2 = 0; l2 < static_cast( p1.next.size() ); l2++) { - EngineBaseObjTexTier& p2 = p1.next[l2]; + EngineBaseObjDataTier& p2 = p1.next[l2]; l->Debug(" l2:\n"); + /* l->Debug(" tex1: %s (id: %u)\n", p2.tex1Name.c_str(), p2.tex1.id); l->Debug(" tex2: %s (id: %u)\n", p2.tex2Name.c_str(), p2.tex2.id); @@ -875,6 +811,7 @@ void CEngine::DebugObject(int objRank) l->Debug(" staticBufferId: %u\n", p3.buffer); l->Debug(" updateStaticBuffer: %s\n", p3.updateStaticBuffer ? "true" : "false"); } + // */ } } @@ -1018,40 +955,6 @@ int CEngine::GetObjectTotalTriangles(int objRank) return m_baseObjects[baseObjRank].totalTriangles; } -EngineBaseObjDataTier* CEngine::FindTriangles(int objRank, int state, std::string tex1Name, - std::string tex2Name) -{ - assert(objRank >= 0 && objRank < static_cast( m_objects.size() )); - - int baseObjRank = m_objects[objRank].baseObjRank; - if (baseObjRank == -1) - return nullptr; - - assert(baseObjRank >= 0 && baseObjRank < static_cast( m_baseObjects.size() )); - - EngineBaseObject& p1 = m_baseObjects[baseObjRank]; - - for (int l2 = 0; l2 < static_cast( p1.next.size() ); l2++) - { - EngineBaseObjTexTier& p2 = p1.next[l2]; - - if (p2.tex1Name != tex1Name) - continue; - - for (int l3 = 0; l3 < static_cast( p2.next.size() ); l3++) - { - EngineBaseObjDataTier& p3 = p2.next[l3]; - - if ( (p3.state & (~(ENG_RSTATE_DUAL_BLACK|ENG_RSTATE_DUAL_WHITE))) != state) - continue; - - return &p3; - } - } - - return nullptr; -} - int CEngine::GetPartialTriangles(int objRank, float percent, int maxCount, std::vector& triangles) { @@ -1073,57 +976,48 @@ int CEngine::GetPartialTriangles(int objRank, float percent, int maxCount, for (int l2 = 0; l2 < static_cast( p1.next.size() ); l2++) { - EngineBaseObjTexTier& p2 = p1.next[l2]; + EngineBaseObjDataTier& p3 = p1.next[l2]; - for (int l3 = 0; l3 < static_cast( p2.next.size() ); l3++) + if (p3.type == EngineTriangleType::TRIANGLES) { - EngineBaseObjDataTier& p3 = p2.next[l3]; - - if (p3.type == EngineTriangleType::TRIANGLES) + for (size_t i = 0; i < p3.vertices.size(); i += 3) { - for (int i = 0; i < static_cast( p3.vertices.size() ); i += 3) - { - if (static_cast(actualCount) / total >= percent) - break; + if (static_cast(actualCount) / total >= percent) + break; - if (actualCount >= maxCount) - break; + if (actualCount >= maxCount) + break; - EngineTriangle t; - t.triangle[0] = p3.vertices[i]; - t.triangle[1] = p3.vertices[i+1]; - t.triangle[2] = p3.vertices[i+2]; - t.state = p3.state; - t.tex1Name = p2.tex1Name; - t.tex2Name = p2.tex2Name; + EngineTriangle t; + t.triangle[0] = p3.vertices[i]; + t.triangle[1] = p3.vertices[i + 1]; + t.triangle[2] = p3.vertices[i + 2]; + t.material = p3.material; - triangles.push_back(t); + triangles.push_back(t); - ++actualCount; - } + ++actualCount; } - else if (p3.type == EngineTriangleType::SURFACE) + } + else if (p3.type == EngineTriangleType::SURFACE) + { + for (size_t i = 0; i < p3.vertices.size(); i += 1) { - for (int i = 0; i < static_cast( p3.vertices.size() ); i += 1) - { - if (static_cast(actualCount) / total >= percent) - break; + if (static_cast(actualCount) / total >= percent) + break; - if (actualCount >= maxCount) - break; + if (actualCount >= maxCount) + break; - EngineTriangle t; - t.triangle[0] = p3.vertices[i]; - t.triangle[1] = p3.vertices[i+1]; - t.triangle[2] = p3.vertices[i+2]; - t.state = p3.state; - t.tex1Name = p2.tex1Name; - t.tex2Name = p2.tex2Name; + EngineTriangle t; + t.triangle[0] = p3.vertices[i]; + t.triangle[1] = p3.vertices[i + 1]; + t.triangle[2] = p3.vertices[i + 2]; + t.material = p3.material; - triangles.push_back(t); + triangles.push_back(t); - ++actualCount; - } + ++actualCount; } } } @@ -1143,25 +1037,18 @@ void CEngine::ChangeSecondTexture(int objRank, const std::string& tex2Name) EngineBaseObject& p1 = m_baseObjects[baseObjRank]; - for (int l2 = 0; l2 < static_cast( p1.next.size() ); l2++) + for (auto& data : p1.next) { - if (p1.next[l2].tex2Name == tex2Name) + if (data.material.detailTexture == tex2Name) continue; // already new - std::string tex1Name = p1.next[l2].tex1Name; - EngineBaseObjTexTier& newP2 = AddLevel2(p1, tex1Name, tex2Name); - newP2.next.insert(newP2.next.end(), p1.next[l2].next.begin(), p1.next[l2].next.end()); - p1.next[l2].next.clear(); + data.material.detailTexture = tex2Name; - if (!newP2.tex1.Valid() && !newP2.tex1Name.empty()) - newP2.tex1 = LoadTexture("textures/"+newP2.tex1Name); - - if (!newP2.tex2.Valid() && !newP2.tex2Name.empty()) - newP2.tex2 = LoadTexture("textures/"+newP2.tex2Name); + data.detailTexture = LoadTexture("textures/" + tex2Name); } } -void CEngine::SetUVTransform(int objRank, int state, const glm::vec2& offset, const glm::vec2& scale) +void CEngine::SetUVTransform(int objRank, const std::string& tag, const glm::vec2& offset, const glm::vec2& scale) { assert(objRank >= 0 && objRank < static_cast(m_objects.size())); @@ -1173,19 +1060,12 @@ void CEngine::SetUVTransform(int objRank, int state, const glm::vec2& offset, co EngineBaseObject& p1 = m_baseObjects[baseObjRank]; - for (size_t l2 = 0; l2 < p1.next.size(); l2++) + for (auto& data : p1.next) { - EngineBaseObjTexTier& p2 = p1.next[l2]; - - for (size_t l3 = 0; l3 < p2.next.size(); l3++) + if (data.material.tag == tag) { - EngineBaseObjDataTier& p3 = p2.next[l3]; - - if (p3.state & state) - { - p3.uvOffset = offset; - p3.uvScale = scale; - } + data.uvOffset = offset; + data.uvScale = scale; } } } @@ -1515,36 +1395,28 @@ void CEngine::UpdateGeometry() if (! m_updateGeometry) return; - for (int baseObjRank = 0; baseObjRank < static_cast( m_baseObjects.size() ); baseObjRank++) + for (auto& object : m_baseObjects) { - EngineBaseObject &p1 = m_baseObjects[baseObjRank]; - if (! p1.used) + if (!object.used) continue; - p1.bboxMin = { 0, 0, 0 }; - p1.bboxMax = { 0, 0, 0 }; + object.bboxMin = { 0, 0, 0 }; + object.bboxMax = { 0, 0, 0 }; - for (int l2 = 0; l2 < static_cast( p1.next.size() ); l2++) + for (auto& data : object.next) { - EngineBaseObjTexTier& p2 = p1.next[l2]; - - for (int l3 = 0; l3 < static_cast( p2.next.size() ); l3++) + for (const auto& vertex : data.vertices) { - EngineBaseObjDataTier& p3 = p2.next[l3]; - - for (int i = 0; i < static_cast( p3.vertices.size() ); i++) - { - p1.bboxMin.x = Math::Min(p3.vertices[i].position.x, p1.bboxMin.x); - p1.bboxMin.y = Math::Min(p3.vertices[i].position.y, p1.bboxMin.y); - p1.bboxMin.z = Math::Min(p3.vertices[i].position.z, p1.bboxMin.z); - p1.bboxMax.x = Math::Max(p3.vertices[i].position.x, p1.bboxMax.x); - p1.bboxMax.y = Math::Max(p3.vertices[i].position.y, p1.bboxMax.y); - p1.bboxMax.z = Math::Max(p3.vertices[i].position.z, p1.bboxMax.z); - } + object.bboxMin.x = Math::Min(vertex.position.x, object.bboxMin.x); + object.bboxMin.y = Math::Min(vertex.position.y, object.bboxMin.y); + object.bboxMin.z = Math::Min(vertex.position.z, object.bboxMin.z); + object.bboxMax.x = Math::Max(vertex.position.x, object.bboxMax.x); + object.bboxMax.y = Math::Max(vertex.position.y, object.bboxMax.y); + object.bboxMax.z = Math::Max(vertex.position.z, object.bboxMax.z); } } - p1.boundingSphere = Math::BoundingSphereForBox(p1.bboxMin, p1.bboxMax); + object.boundingSphere = Math::BoundingSphereForBox(object.bboxMin, object.bboxMax); } m_updateGeometry = false; @@ -1565,6 +1437,10 @@ void CEngine::UpdateStaticBuffer(EngineBaseObjDataTier& p4) else { p4.buffer->SetType(type); + + if (p4.buffer->Size() != p4.vertices.size()) + p4.buffer->Resize(p4.vertices.size()); + p4.buffer->SetData(p4.vertices.data(), 0, p4.vertices.size()); p4.buffer->Update(); } @@ -1579,25 +1455,15 @@ void CEngine::UpdateStaticBuffers() m_updateStaticBuffers = false; - for (int baseObjRank = 0; baseObjRank < static_cast( m_baseObjects.size() ); baseObjRank++) + for (auto& object : m_baseObjects) { - EngineBaseObject& p1 = m_baseObjects[baseObjRank]; - if (! p1.used) + if (!object.used) continue; - for (int l2 = 0; l2 < static_cast( p1.next.size() ); l2++) + for (auto& data : object.next) { - EngineBaseObjTexTier& p2 = p1.next[l2]; - - for (int l3 = 0; l3 < static_cast( p2.next.size() ); l3++) - { - EngineBaseObjDataTier& p3 = p2.next[l3]; - - if (! p3.updateStaticBuffer) - continue; - - UpdateStaticBuffer(p3); - } + if (data.updateStaticBuffer) + UpdateStaticBuffer(data); } } } @@ -1683,36 +1549,31 @@ int CEngine::DetectObject(const glm::vec2& mouse, glm::vec3& targetPos, bool ter for (int l2 = 0; l2 < static_cast( p1.next.size() ); l2++) { - EngineBaseObjTexTier& p2 = p1.next[l2]; + EngineBaseObjDataTier& data = p1.next[l2]; - for (int l3 = 0; l3 < static_cast( p2.next.size() ); l3++) + if (data.type == EngineTriangleType::TRIANGLES) { - EngineBaseObjDataTier& p3 = p2.next[l3]; - - if (p3.type == EngineTriangleType::TRIANGLES) + for (int i = 0; i < static_cast(data.vertices.size()); i += 3) { - for (int i = 0; i < static_cast( p3.vertices.size() ); i += 3) + float dist = 0.0f; + if (DetectTriangle(mouse, &data.vertices[i], objRank, dist, pos) && dist < min) { - float dist = 0.0f; - if (DetectTriangle(mouse, &p3.vertices[i], objRank, dist, pos) && dist < min) - { - min = dist; - nearest = objRank; - targetPos = pos; - } + min = dist; + nearest = objRank; + targetPos = pos; } } - else if (p3.type == EngineTriangleType::SURFACE) + } + else if (data.type == EngineTriangleType::SURFACE) + { + for (int i = 0; i < static_cast(data.vertices.size()) - 2; i += 1) { - for (int i = 0; i < static_cast( p3.vertices.size() ) - 2; i += 1) + float dist = 0.0f; + if (DetectTriangle(mouse, &data.vertices[i], objRank, dist, pos) && dist < min) { - float dist = 0.0f; - if (DetectTriangle(mouse, &p3.vertices[i], objRank, dist, pos) && dist < min) - { - min = dist; - nearest = objRank; - targetPos = pos; - } + min = dist; + nearest = objRank; + targetPos = pos; } } } @@ -2049,29 +1910,27 @@ bool CEngine::LoadAllTextures() if (! p1.used) continue; - for (int l2 = 0; l2 < static_cast( p1.next.size() ); l2++) + for (auto& data : p1.next) { - EngineBaseObjTexTier& p2 = p1.next[l2]; - - if (! p2.tex1Name.empty()) + if (!data.material.albedoTexture.empty()) { if (terrain) - p2.tex1 = LoadTexture("textures/"+p2.tex1Name, m_terrainTexParams); + data.albedoTexture = LoadTexture("textures/" + data.material.albedoTexture, m_terrainTexParams); else - p2.tex1 = LoadTexture("textures/"+p2.tex1Name); + data.albedoTexture = LoadTexture("textures/" + data.material.albedoTexture); - if (! p2.tex1.Valid()) + if (!data.albedoTexture.Valid()) ok = false; } - if (! p2.tex2Name.empty()) + if (!data.material.detailTexture.empty()) { if (terrain) - p2.tex2 = LoadTexture("textures/"+p2.tex2Name, m_terrainTexParams); + data.detailTexture = LoadTexture("textures/" + data.material.detailTexture, m_terrainTexParams); else - p2.tex2 = LoadTexture("textures/"+p2.tex2Name); + data.detailTexture = LoadTexture("textures/" + data.material.detailTexture); - if (! p2.tex2.Valid()) + if (!data.detailTexture.Valid()) ok = false; } } @@ -3017,19 +2876,12 @@ void CEngine::Draw3DScene() if (! p1.used) continue; - for (int l2 = 0; l2 < static_cast( p1.next.size() ); l2++) + for (auto& data : p1.next) { - EngineBaseObjTexTier& p2 = p1.next[l2]; + terrainRenderer->SetPrimaryTexture(data.albedoTexture); + terrainRenderer->SetSecondaryTexture(data.detailTexture); - terrainRenderer->SetPrimaryTexture(p2.tex1); - terrainRenderer->SetSecondaryTexture(p2.tex2); - - for (int l3 = 0; l3 < static_cast( p2.next.size() ); l3++) - { - EngineBaseObjDataTier& p3 = p2.next[l3]; - - terrainRenderer->DrawObject(m_objects[objRank].transform, p3.buffer); - } + terrainRenderer->DrawObject(m_objects[objRank].transform, data.buffer); } } @@ -3098,46 +2950,36 @@ void CEngine::Draw3DScene() //m_lightMan->UpdateDeviceLights(m_objects[objRank].type); - for (int l2 = 0; l2 < static_cast( p1.next.size() ); l2++) + for (auto& data : p1.next) { - EngineBaseObjTexTier& p2 = p1.next[l2]; - - objectRenderer->SetPrimaryTexture(p2.tex1); - objectRenderer->SetSecondaryTexture(p2.tex2); - - for (int l3 = 0; l3 < static_cast( p2.next.size() ); l3++) + if (m_objects[objRank].ghost) // transparent ? { - EngineBaseObjDataTier& p3 = p2.next[l3]; - - if (m_objects[objRank].ghost) // transparent ? - { - transparent = true; - continue; - } - - if (p3.state & ENG_RSTATE_ALPHA) - { - objectRenderer->SetAlphaScissor(0.2f); - } - else - { - objectRenderer->SetAlphaScissor(0.0f); - } - - if ((p3.state & ENG_RSTATE_TCOLOR_BLACK) - || (p3.state & ENG_RSTATE_TCOLOR_WHITE) - || (p3.state & ENG_RSTATE_TCOLOR_ALPHA)) - objectRenderer->SetPrimaryTextureEnabled(false); - else - objectRenderer->SetPrimaryTextureEnabled(true); - - float dirty = ((p3.state & ENG_RSTATE_DUAL_BLACK) && m_dirty) ? 1.0 : 0.0; - objectRenderer->SetDirty(dirty); - objectRenderer->SetColor({ 1.0f, 1.0f, 1.0f, 1.0f }); - objectRenderer->SetCullFace((p3.state& ENG_RSTATE_2FACE) > 0 ? CullFace::NONE : CullFace::BACK); - objectRenderer->SetUVTransform(p3.uvOffset, p3.uvScale); - objectRenderer->DrawObject(p3.buffer); + transparent = true; + continue; } + + objectRenderer->SetPrimaryTexture(data.albedoTexture); + objectRenderer->SetSecondaryTexture(data.detailTexture); + + if (data.material.alphaMode != AlphaMode::OPAQUE) + { + objectRenderer->SetAlphaScissor(data.material.alphaThreshold); + } + else + { + objectRenderer->SetAlphaScissor(0.0f); + } + + objectRenderer->SetPrimaryTextureEnabled(true); + + float dirty = ((data.material.variableDetail + || !data.material.detailTexture.empty()) && m_dirty) + ? 1.0 : 0.0; + objectRenderer->SetDirty(dirty); + objectRenderer->SetColor({ 1.0f, 1.0f, 1.0f, 1.0f }); + objectRenderer->SetCullFace(data.material.cullFace); + objectRenderer->SetUVTransform(data.uvOffset, data.uvScale); + objectRenderer->DrawObject(data.buffer); } } @@ -3184,26 +3026,19 @@ void CEngine::Draw3DScene() objectRenderer->SetModelMatrix(m_objects[objRank].transform); - for (int l2 = 0; l2 < static_cast( p1.next.size() ); l2++) + for (auto& data : p1.next) { - EngineBaseObjTexTier& p2 = p1.next[l2]; + objectRenderer->SetPrimaryTexture(data.albedoTexture); + objectRenderer->SetSecondaryTexture(data.detailTexture); - objectRenderer->SetPrimaryTexture(p2.tex1); - objectRenderer->SetSecondaryTexture(p2.tex2); + if (!m_objects[objRank].ghost) + continue; - for (int l3 = 0; l3 < static_cast( p2.next.size() ); l3++) - { - EngineBaseObjDataTier& p3 = p2.next[l3]; - - if (!m_objects[objRank].ghost) - continue; - - 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); - } + float dirty = 1.0f;// (data.state& ENG_RSTATE_DUAL_BLACK) && m_dirty ? 1.0 : 0.0; + objectRenderer->SetDirty(dirty); + objectRenderer->SetColor(tColor); + objectRenderer->SetUVTransform(data.uvOffset, data.uvScale); + objectRenderer->DrawObject(data.buffer); } } } @@ -3663,18 +3498,11 @@ void CEngine::RenderShadowMap() renderer->SetModelMatrix(m_objects[objRank].transform); - for (int l2 = 0; l2 < static_cast(p1.next.size()); l2++) + for (auto& data : p1.next) { - EngineBaseObjTexTier& p2 = p1.next[l2]; + renderer->SetTexture(data.albedoTexture); - renderer->SetTexture(p2.tex1); - - for (int l3 = 0; l3 < static_cast(p2.next.size()); l3++) - { - EngineBaseObjDataTier& p3 = p2.next[l3]; - - renderer->DrawObject(p3.buffer, true); - } + renderer->DrawObject(data.buffer, true); } } } @@ -3842,23 +3670,12 @@ void CEngine::DrawInterface() //m_lightMan->UpdateDeviceLights(m_objects[objRank].type); - for (int l2 = 0; l2 < static_cast( p1.next.size() ); l2++) + for (auto& data : p1.next) { - EngineBaseObjTexTier& p2 = p1.next[l2]; + renderer->SetPrimaryTexture(data.albedoTexture); + renderer->SetSecondaryTexture(data.detailTexture); - renderer->SetPrimaryTexture(p2.tex1); - renderer->SetSecondaryTexture(p2.tex2); - - for (int l3 = 0; l3 < static_cast( p2.next.size() ); l3++) - { - EngineBaseObjDataTier& p3 = p2.next[l3]; - - //SetMaterial(p3.material); - //SetState(p3.state); - - renderer->DrawObject(p3.buffer); - //DrawObject(p3); - } + renderer->DrawObject(data.buffer); } } @@ -4852,87 +4669,62 @@ void CEngine::DrawStats() void CEngine::DrawTimer() { - //SetState(ENG_RSTATE_TEXT); - glm::vec2 pos(0.98f, 0.98f-m_text->GetAscent(FONT_COMMON, 15.0f)); m_text->DrawText(m_timerText, FONT_COMMON, 15.0f, pos, 1.0f, TEXT_ALIGN_RIGHT, 0, Color(1.0f, 1.0f, 1.0f, 1.0f)); } void CEngine::AddBaseObjTriangles(int baseObjRank, const std::vector& triangles) { - std::vector vs(3, Vertex3D{}); + EngineBaseObject& p1 = m_baseObjects[baseObjRank]; + + std::array vertices; for (const auto& triangle : triangles) { - vs[0] = triangle.p1; - vs[1] = triangle.p2; - vs[2] = triangle.p3; + vertices[0] = triangle.p1; + vertices[1] = triangle.p2; + vertices[2] = triangle.p3; - int state = GetEngineState(triangle); + Material material; std::string tex1Name; if (!triangle.tex1Name.empty()) - tex1Name = "objects/" + triangle.tex1Name; + material.albedoTexture = "objects/" + triangle.tex1Name; std::string tex2Name; if (triangle.variableTex2) - tex2Name = GetSecondTexture(); + material.detailTexture = GetSecondTexture(); else - tex2Name = triangle.tex2Name; + material.detailTexture = triangle.tex2Name; - AddBaseObjTriangles(baseObjRank, vs, state, tex1Name, tex2Name); + material.alphaMode = triangle.alphaMode; + material.alphaThreshold = triangle.alphaThreshold; + material.cullFace = triangle.doubleSided ? CullFace::NONE : CullFace::BACK; + material.tag = triangle.tag; + + EngineBaseObjDataTier& data = AddLevel(p1, EngineTriangleType::TRIANGLES, material); + + data.vertices.insert(data.vertices.end(), vertices.begin(), vertices.end()); + + data.updateStaticBuffer = true; + m_updateStaticBuffers = true; + + for (size_t i = 0; i < vertices.size(); i++) + { + p1.bboxMin.x = Math::Min(vertices[i].position.x, p1.bboxMin.x); + p1.bboxMin.y = Math::Min(vertices[i].position.y, p1.bboxMin.y); + p1.bboxMin.z = Math::Min(vertices[i].position.z, p1.bboxMin.z); + p1.bboxMax.x = Math::Max(vertices[i].position.x, p1.bboxMax.x); + p1.bboxMax.y = Math::Max(vertices[i].position.y, p1.bboxMax.y); + p1.bboxMax.z = Math::Max(vertices[i].position.z, p1.bboxMax.z); + } + + p1.boundingSphere = Math::BoundingSphereForBox(p1.bboxMin, p1.bboxMax); + + p1.totalTriangles += vertices.size() / 3; } } -int CEngine::GetEngineState(const ModelTriangle& triangle) -{ - int state = 0; - - if (!triangle.tex2Name.empty() || triangle.variableTex2) - state |= ENG_RSTATE_DUAL_BLACK; - - switch (triangle.transparentMode) - { - case ModelTransparentMode::None: - break; - - case ModelTransparentMode::AlphaChannel: - state |= ENG_RSTATE_ALPHA; - break; - - case ModelTransparentMode::MapBlackToAlpha: - state |= ENG_RSTATE_TTEXTURE_BLACK; - break; - - case ModelTransparentMode::MapWhiteToAlpha: - state |= ENG_RSTATE_TTEXTURE_WHITE; - break; - } - - switch (triangle.specialMark) - { - case ModelSpecialMark::None: - break; - - case ModelSpecialMark::Part1: - state |= ENG_RSTATE_PART1; - break; - - case ModelSpecialMark::Part2: - state |= ENG_RSTATE_PART2; - break; - - case ModelSpecialMark::Part3: - state |= ENG_RSTATE_PART3; - break; - } - - if (triangle.doubleSided) - state |= ENG_RSTATE_2FACE; - - return state; -} - void CEngine::UpdateObjectShadowSpotNormal(int objRank) { assert(objRank >= 0 && objRank < static_cast( m_objects.size() )); diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index 3a0d0d09..39dbadb4 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -73,62 +73,6 @@ struct ModelShadowSpot; struct ModelTriangle; -/** - * \enum EngineRenderState - * \brief Render state of graphics engine - * - * States are used for settings certain modes, for instance texturing and blending. - * The enum is a bitmask and some of the states can be OR'd together. - */ -enum EngineRenderState -{ - //! Normal opaque materials - ENG_RSTATE_NORMAL = 0, - //! The transparent texture (black = no) - ENG_RSTATE_TTEXTURE_BLACK = (1<<0), - //! The transparent texture (white = no) - ENG_RSTATE_TTEXTURE_WHITE = (1<<1), - //! The transparent diffuse color - ENG_RSTATE_TDIFFUSE = (1<<2), - //! Light texture (ambient max) - ENG_RSTATE_LIGHT = (1<<5), - //! Double black texturing - ENG_RSTATE_DUAL_BLACK = (1<<6), - //! Double white texturing - ENG_RSTATE_DUAL_WHITE = (1<<7), - //! Part 1 (no change in. MOD!) - ENG_RSTATE_PART1 = (1<<8), - //! Part 2 - ENG_RSTATE_PART2 = (1<<9), - //! Part 3 - ENG_RSTATE_PART3 = (1<<10), - //! Part 4 - ENG_RSTATE_PART4 = (1<<11), - //! Double-sided face - ENG_RSTATE_2FACE = (1<<12), - //! Image using alpha channel - ENG_RSTATE_ALPHA = (1<<13), - //! Always use 2nd floor texturing - ENG_RSTATE_SECOND = (1<<14), - //! Causes the fog - ENG_RSTATE_FOG = (1<<15), - //! The transparent color (black = no) - ENG_RSTATE_TCOLOR_BLACK = (1<<16), - //! The transparent color (white = no) - ENG_RSTATE_TCOLOR_WHITE = (1<<17), - //! Mode for rendering text - ENG_RSTATE_TEXT = (1<<18), - //! Only opaque texture, no blending, etc. - ENG_RSTATE_OPAQUE_TEXTURE = (1<<19), - //! Only opaque color, no texture, blending, etc. - ENG_RSTATE_OPAQUE_COLOR = (1<<20), - //! Texture using alpha channel - ENG_RSTATE_TTEXTURE_ALPHA = (1<<21), - //! Color with transparency - ENG_RSTATE_TCOLOR_ALPHA = (1<<22) -}; - - /** * \enum EngineTriangleType * \brief Type of triangles drawn for engine objects @@ -149,12 +93,8 @@ struct EngineTriangle { //! Triangle vertices Vertex3D triangle[3]; - //! Render state - int state = ENG_RSTATE_NORMAL; - //! 1st texture - std::string tex1Name; - //! 2nd texture - std::string tex2Name; + //! Triangle material + Material material; }; /** @@ -186,33 +126,19 @@ enum EngineObjectType struct EngineBaseObjDataTier { EngineTriangleType type = EngineTriangleType::TRIANGLES; - int state = ENG_RSTATE_NORMAL; + Material material = {}; + std::vector vertices; CVertexBuffer* buffer = nullptr; bool updateStaticBuffer = false; + + Texture albedoTexture; + Texture detailTexture; + glm::vec2 uvOffset = { 0.0f, 0.0f }; glm::vec2 uvScale = { 1.0f, 1.0f }; }; -/** - * \struct EngineBaseObjTexTier - * \brief Tier 2 of base object tree (textures) - */ -struct EngineBaseObjTexTier -{ - std::string tex1Name; - Texture tex1; - std::string tex2Name; - Texture tex2; - std::vector next; - - inline EngineBaseObjTexTier(const std::string& tex1Name = "", - const std::string& tex2Name = "") - : tex1Name(tex1Name) - , tex2Name(tex2Name) - {} -}; - /** * \struct BaseEngineObject * \brief Base (template) object - geometry for engine objects @@ -231,8 +157,8 @@ struct EngineBaseObject glm::vec3 bboxMax{ 0, 0, 0 }; //! A bounding sphere that contains all the vertices in this EngineBaseObject Math::Sphere boundingSphere; - //! Next tier (Tex) - std::vector next; + //! Next tier + std::vector next; inline void LoadDefault() { @@ -545,17 +471,6 @@ enum EngineMouseType * Shadows are drawn as circular spots on the ground, except for shadows for worms, which have * special mode for them. * - * \section RenderStates Render States - * - * Almost every primitive drawn on screen is drawn in state set through EngineRenderState enum. - * In some functions, custom modes are still set, using CDevice's SetRenderState. However, it - * will be subject to removal in the future. Generally, setting render states should be minimized - * to avoid unnecessary overhead. - * - * Some states are clearly the result of legacy drawing and texturing methods. For example, TTEXTURE - * states should really be removed and the textures changed to ones with alpha channel. In the future, - * the whole modesetting code will probably be refactored to something more maintainable. - * * \section Textures Textures * * Textures are loaded from a texture subdir in data directory. In the old code, textures were identified @@ -714,12 +629,10 @@ public: void CopyBaseObject(int sourceBaseObjRank, int destBaseObjRank); //! Adds triangles to given object with the specified params - void AddBaseObjTriangles(int baseObjRank, const std::vector& triangles); + void AddBaseObjTriangles(int baseObjRank, const std::vector& triangles); - //! Adds a tier 4 engine object directly - void AddBaseObjQuick(int baseObjRank, const EngineBaseObjDataTier& buffer, - std::string tex1Name, std::string tex2Name, - bool globalUpdate); + void AddBaseObjTriangles(int baseObjRank, const std::vector& vertices, + const Material& material, EngineTriangleType type); // Objects @@ -765,9 +678,6 @@ public: //! Returns the total number of triangles of given object int GetObjectTotalTriangles(int objRank); - //! Returns the first found tier 4 engine object for the given params or nullptr if not found - EngineBaseObjDataTier* FindTriangles(int objRank, int state, std::string tex1Name, std::string tex2Name); - //! Returns a partial list of triangles for given object int GetPartialTriangles(int objRank, float percent, int maxCount, std::vector& triangles); @@ -775,7 +685,7 @@ public: //! Changes the 2nd texure for given object void ChangeSecondTexture(int objRank, const std::string& tex2Name); - void SetUVTransform(int objRank, int state, const glm::vec2& offset, const glm::vec2& scale); + void SetUVTransform(int objRank, const std::string& tag, 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. */ @@ -1209,10 +1119,8 @@ protected: void DrawTimer(); void RenderPendingDebugDraws(); - //! Creates a new tier 2 object (texture) - EngineBaseObjTexTier& AddLevel2(EngineBaseObject& p1, const std::string& tex1Name, const std::string& tex2Name); - //! Creates a new tier 3 object (data) - EngineBaseObjDataTier& AddLevel3(EngineBaseObjTexTier &p3, EngineTriangleType type, int state); + //! Creates a new tier + EngineBaseObjDataTier& AddLevel(EngineBaseObject& p3, EngineTriangleType type, const Material& material); //! Create texture and add it to cache Texture CreateTexture(const std::string &texName, const TextureCreateParams ¶ms, CImage* image = nullptr); @@ -1247,11 +1155,6 @@ protected: //! Updates static buffers of changed objects void UpdateStaticBuffers(); - void AddBaseObjTriangles(int baseObjRank, const std::vector& vertices, - int state, std::string tex1Name, std::string tex2Name); - - int GetEngineState(const ModelTriangle& triangle); - struct WriteScreenShotData { std::unique_ptr img; diff --git a/src/graphics/engine/oldmodelmanager.cpp b/src/graphics/engine/oldmodelmanager.cpp index f8397a7e..5c3b5652 100644 --- a/src/graphics/engine/oldmodelmanager.cpp +++ b/src/graphics/engine/oldmodelmanager.cpp @@ -86,8 +86,8 @@ bool COldModelManager::LoadModel(const std::string& fileName, bool mirrored, int if (mirrored) Mirror(modelInfo.triangles); - if (variant != 0) - ChangeVariant(modelInfo.triangles, variant); + //if (variant != 0) + // ChangeVariant(modelInfo.triangles, variant); FileInfo fileInfo(fileName, mirrored, variant); m_models[fileInfo] = modelInfo; @@ -209,7 +209,7 @@ void COldModelManager::ChangeVariant(std::vector& triangles, int triangles[i].tex1Name == "drawer.png" || triangles[i].tex1Name == "subm.png" ) { - triangles[i].tex1Name += StrUtils::ToString(variant); + //triangles[i].tex1Name += StrUtils::ToString(variant); } } } diff --git a/src/graphics/engine/particle.cpp b/src/graphics/engine/particle.cpp index 741aad60..b61eb0a9 100644 --- a/src/graphics/engine/particle.cpp +++ b/src/graphics/engine/particle.cpp @@ -3400,8 +3400,9 @@ void CParticle::DrawParticle(int sheet) if (m_particle[i].sheet != sheet) continue; if (m_particle[i].type == PARTIPART) continue; - auto texture = m_engine->LoadTexture(!m_triangle[i].tex1Name.empty() - ? "textures/" + m_triangle[i].tex1Name : ""); + auto texture = m_engine->LoadTexture(!m_triangle[i].material.albedoTexture.empty() + ? "textures/" + m_triangle[i].material.albedoTexture + : ""); m_renderer->SetTexture(texture); //m_engine->SetState(m_triangle[i].state); diff --git a/src/graphics/engine/terrain.cpp b/src/graphics/engine/terrain.cpp index 357b5445..341e176b 100644 --- a/src/graphics/engine/terrain.cpp +++ b/src/graphics/engine/terrain.cpp @@ -630,16 +630,8 @@ bool CTerrain::CreateMosaic(int ox, int oy, int step, int objRank) for (int y = 0; y < brick; y += step) { - EngineBaseObjDataTier buffer; - buffer.vertices.reserve(total); - - buffer.type = EngineTriangleType::SURFACE; - - buffer.state = ENG_RSTATE_NORMAL; - - buffer.state |= ENG_RSTATE_SECOND; - if (step == 1) - buffer.state |= ENG_RSTATE_DUAL_BLACK; + std::vector vertices; + vertices.reserve(total); for (int x = 0; x <= brick; x += step) { @@ -723,11 +715,19 @@ bool CTerrain::CreateMosaic(int ox, int oy, int step, int objRank) p2.uv2.y = (p2.uv2.y+pixel)*(1.0f-pixel)/(1.0f+pixel); - buffer.vertices.push_back(p1); - buffer.vertices.push_back(p2); + vertices.push_back(p1); + vertices.push_back(p2); } - m_engine->AddBaseObjQuick(baseObjRank, buffer, texName1, texName2, true); + Gfx::Material material; + material.albedoTexture = texName1; + material.detailTexture = texName2; + material.tag = "brick_" + + std::to_string(mx + 1) + "_" + + std::to_string(my + 1) + "_" + + std::to_string(y + 1); + + m_engine->AddBaseObjTriangles(baseObjRank, vertices, material, EngineTriangleType::SURFACE); } } } diff --git a/src/graphics/model/model_input.cpp b/src/graphics/model/model_input.cpp index 87158ab6..e98213b4 100644 --- a/src/graphics/model/model_input.cpp +++ b/src/graphics/model/model_input.cpp @@ -88,8 +88,8 @@ namespace ModelInput ModelCrashSphere ParseCrashSphere(const std::string& text); ModelShadowSpot ParseShadowSpot(const std::string& text); Math::Sphere ParseCameraCollisionSphere(const std::string& text); - ModelTransparentMode ParseTransparentMode(const std::string& text); - ModelSpecialMark ParseSpecialMark(const std::string& text); + AlphaMode ParseTransparentMode(const std::string& text); + std::string ParseSpecialMark(const std::string& text); void ConvertOldTex1Name(ModelTriangle& triangle, const char* tex1Name); void ConvertFromOldRenderState(ModelTriangle& triangle, int state); @@ -397,10 +397,13 @@ CModelMesh ModelInput::ReadTextMesh(std::istream& stream) t.tex2Name = ReadLineString(stream, "tex2"); t.variableTex2 = ReadLineString(stream, "var_tex2") == std::string("Y"); - t.transparentMode = ParseTransparentMode(ReadLineString(stream, "trans_mode")); - t.specialMark = ParseSpecialMark(ReadLineString(stream, "mark")); + t.alphaMode = ParseTransparentMode(ReadLineString(stream, "trans_mode")); + t.tag = ParseSpecialMark(ReadLineString(stream, "mark")); t.doubleSided = ReadLineString(stream, "dbl_side") == std::string("Y"); + if (t.alphaMode != AlphaMode::OPAQUE) + t.alphaThreshold = 0.5f; + mesh.AddTriangle(t); } @@ -638,22 +641,21 @@ void ModelInput::ConvertOldTex1Name(ModelTriangle& triangle, const char* tex1Nam void ModelInput::ConvertFromOldRenderState(ModelTriangle& triangle, int state) { if (triangle.tex1Name == "plant.png" || (state & static_cast(ModelRenderState::Alpha)) != 0) - triangle.transparentMode = ModelTransparentMode::AlphaChannel; - else if ((state & static_cast(ModelRenderState::TTextureBlack)) != 0) - triangle.transparentMode = ModelTransparentMode::MapBlackToAlpha; - else if ((state & static_cast(ModelRenderState::TTextureWhite)) != 0) - triangle.transparentMode = ModelTransparentMode::MapWhiteToAlpha; + { + triangle.alphaMode = AlphaMode::MASK; + triangle.alphaThreshold = 0.5f; + } else - triangle.transparentMode = ModelTransparentMode::None; + triangle.alphaMode = AlphaMode::OPAQUE; if ((state & static_cast(ModelRenderState::Part1)) != 0) - triangle.specialMark = ModelSpecialMark::Part1; + triangle.tag = "tracker_right"; else if ((state & static_cast(ModelRenderState::Part2)) != 0) - triangle.specialMark = ModelSpecialMark::Part2; + triangle.tag = "tracker_left"; else if ((state & static_cast(ModelRenderState::Part3)) != 0) - triangle.specialMark = ModelSpecialMark::Part3; + triangle.tag = "energy"; else - triangle.specialMark = ModelSpecialMark::None; + triangle.tag = ""; triangle.doubleSided = (state & static_cast(ModelRenderState::TwoFace)) != 0; } @@ -884,30 +886,26 @@ Math::Sphere ModelInput::ParseCameraCollisionSphere(const std::string& text) return sphere; } -ModelTransparentMode ModelInput::ParseTransparentMode(const std::string& text) +AlphaMode ModelInput::ParseTransparentMode(const std::string& text) { if (text == "none") - return ModelTransparentMode::None; + return AlphaMode::OPAQUE; else if (text == "alpha") - return ModelTransparentMode::AlphaChannel; - else if (text == "map_black") - return ModelTransparentMode::MapBlackToAlpha; - else if (text == "map_white") - return ModelTransparentMode::MapWhiteToAlpha; + return AlphaMode::MASK; else - throw CModelIOException(std::string("Unexpected transparent mode: '") + text + "'"); + return AlphaMode::OPAQUE; } -ModelSpecialMark ModelInput::ParseSpecialMark(const std::string& text) +std::string ModelInput::ParseSpecialMark(const std::string& text) { if (text == "none") - return ModelSpecialMark::None; + return ""; else if (text == "part1") - return ModelSpecialMark::Part1; + return "tracker_right"; else if (text == "part2") - return ModelSpecialMark::Part2; + return "tracker_left"; else if (text == "part3") - return ModelSpecialMark::Part3; + return "energy"; else throw CModelIOException(std::string("Unexpected special mark: '") + text + "'"); } diff --git a/src/graphics/model/model_io_structs.h b/src/graphics/model/model_io_structs.h index 603a7ab5..7b3c279a 100644 --- a/src/graphics/model/model_io_structs.h +++ b/src/graphics/model/model_io_structs.h @@ -50,8 +50,6 @@ enum class ModelLODLevel */ enum class ModelRenderState { - TTextureBlack = 1, //!< old ENG_RSTATE_TTEXTURE_BLACK - TTextureWhite = 2, //!< old ENG_RSTATE_TTEXTURE_WHITE Part1 = 256, //!< old ENG_RSTATE_PART1 Part2 = 512, //!< old ENG_RSTATE_PART2 Part3 = 1024, //!< old ENG_RSTATE_PART3 diff --git a/src/graphics/model/model_triangle.h b/src/graphics/model/model_triangle.h index 2d9ecc65..0f0bffea 100644 --- a/src/graphics/model/model_triangle.h +++ b/src/graphics/model/model_triangle.h @@ -20,38 +20,13 @@ #pragma once #include "graphics/core/color.h" +#include "graphics/core/transparency.h" #include "graphics/core/vertex.h" namespace Gfx { -/** - * \enum ModelSpecialMark - * \brief Special marking for some models - * - * TODO: refactor/remove in the future - */ -enum class ModelSpecialMark -{ - None, - Part1, - Part2, - Part3 -}; - -/** - * \enum ModelTransparentMode - * \brief Describes how to deal with texture transparency - * - * TODO: get rid of it in the future (use only alpha channel) - */ -enum class ModelTransparentMode -{ - None, //!< no transparency - AlphaChannel, //!< use alpha channel - MapBlackToAlpha, //!< map black color to alpha - MapWhiteToAlpha //!< map white color to alpha -}; +enum class AlphaMode : unsigned char; /** * \struct ModelTriangle @@ -74,9 +49,10 @@ struct ModelTriangle //! Whether to render as double-sided surface bool doubleSided = false; //! How to deal with texture transparency - ModelTransparentMode transparentMode = ModelTransparentMode::None; + AlphaMode alphaMode = {}; + float alphaThreshold = 0.5f; //! Special marking - ModelSpecialMark specialMark = ModelSpecialMark::None; + std::string tag = ""; }; } // namespace Gfx diff --git a/src/level/robotmain.cpp b/src/level/robotmain.cpp index 314491a2..9f53e79e 100644 --- a/src/level/robotmain.cpp +++ b/src/level/robotmain.cpp @@ -3973,7 +3973,7 @@ void CRobotMain::ChangeColor() exclu[3] = { 256.0f / 256.0f, 256.0f / 256.0f }; // SatCom screen exclu[4] = { 0.0f, 0.0f }; exclu[5] = { 0.0f, 0.0f }; // terminator - m_engine->ChangeTextureColor("textures/objects/human.png", colorRef1, colorNew1, colorRef2, colorNew2, 0.30f, 0.01f, ts, ti, exclu); + //m_engine->ChangeTextureColor("textures/objects/human.png", colorRef1, colorNew1, colorRef2, colorNew2, 0.30f, 0.01f, ts, ti, exclu); float tolerance; @@ -4020,7 +4020,7 @@ void CRobotMain::ChangeColor() exclu[1] = { 153.0f / 256.0f, 79.0f / 166.0f }; // blue canister exclu[2] = { 0.0f, 0.0f }; exclu[3] = { 0.0f, 0.0f }; // terminator - m_engine->ChangeTextureColor(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; @@ -4038,20 +4038,20 @@ void CRobotMain::ChangeColor() std::string teamStr = StrUtils::ToString(team); if(team == 0) teamStr = ""; - m_engine->ChangeTextureColor("textures/objects/base1.png"+teamStr, "textures/objects/base1.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); - m_engine->ChangeTextureColor("textures/objects/convert.png"+teamStr, "textures/objects/convert.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); - m_engine->ChangeTextureColor("textures/objects/derrick.png"+teamStr, "textures/objects/derrick.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); - m_engine->ChangeTextureColor("textures/objects/factory.png"+teamStr, "textures/objects/factory.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); - m_engine->ChangeTextureColor("textures/objects/lemt.png"+teamStr, "textures/objects/lemt.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); - m_engine->ChangeTextureColor("textures/objects/roller.png"+teamStr, "textures/objects/roller.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); - m_engine->ChangeTextureColor("textures/objects/search.png"+teamStr, "textures/objects/search.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); - m_engine->ChangeTextureColor("textures/objects/rollert.png"+teamStr, "textures/objects/rollert.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); + //m_engine->ChangeTextureColor("textures/objects/base1.png"+teamStr, "textures/objects/base1.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); + //m_engine->ChangeTextureColor("textures/objects/convert.png"+teamStr, "textures/objects/convert.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); + //m_engine->ChangeTextureColor("textures/objects/derrick.png"+teamStr, "textures/objects/derrick.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); + //m_engine->ChangeTextureColor("textures/objects/factory.png"+teamStr, "textures/objects/factory.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); + //m_engine->ChangeTextureColor("textures/objects/lemt.png"+teamStr, "textures/objects/lemt.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); + //m_engine->ChangeTextureColor("textures/objects/roller.png"+teamStr, "textures/objects/roller.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); + //m_engine->ChangeTextureColor("textures/objects/search.png"+teamStr, "textures/objects/search.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); + //m_engine->ChangeTextureColor("textures/objects/rollert.png"+teamStr, "textures/objects/rollert.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, nullptr, 0, true); exclu[0] = { 0.0f / 256.0f, 160.0f / 256.0f }; exclu[1] = { 256.0f / 256.0f, 256.0f / 256.0f }; // pencils exclu[2] = { 0.0f, 0.0f }; exclu[3] = { 0.0f, 0.0f }; // terminator - m_engine->ChangeTextureColor("textures/objects/drawer.png"+teamStr, "textures/objects/drawer.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, exclu, 0, true); + //m_engine->ChangeTextureColor("textures/objects/drawer.png"+teamStr, "textures/objects/drawer.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, exclu, 0, true); exclu[0] = { 237.0f / 256.0f, 176.0f / 256.0f }; exclu[1] = { 256.0f / 256.0f, 220.0f / 256.0f }; // blue canister @@ -4059,7 +4059,7 @@ void CRobotMain::ChangeColor() exclu[3] = { 130.0f / 256.0f, 214.0f / 256.0f }; // safe location exclu[4] = { 0.0f, 0.0f }; exclu[5] = { 0.0f, 0.0f }; // terminator - m_engine->ChangeTextureColor("textures/objects/subm.png"+teamStr, "textures/objects/subm.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, exclu, 0, true); + //m_engine->ChangeTextureColor("textures/objects/subm.png"+teamStr, "textures/objects/subm.png", COLOR_REF_BOT, newColor, colorRef2, colorNew2, 0.10f, -1.0f, ts, ti, exclu, 0, true); } // AlienColor @@ -4068,23 +4068,23 @@ void CRobotMain::ChangeColor() exclu[1] = { 256.0f / 256.0f, 256.0f / 256.0f }; // SatCom exclu[2] = { 0.0f, 0.0f }; exclu[3] = { 0.0f, 0.0f }; // terminator - m_engine->ChangeTextureColor("textures/objects/ant.png", COLOR_REF_ALIEN, m_colorNewAlien, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti, exclu); - m_engine->ChangeTextureColor("textures/objects/mother.png", COLOR_REF_ALIEN, m_colorNewAlien, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti); + //m_engine->ChangeTextureColor("textures/objects/ant.png", COLOR_REF_ALIEN, m_colorNewAlien, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti, exclu); + //m_engine->ChangeTextureColor("textures/objects/mother.png", COLOR_REF_ALIEN, m_colorNewAlien, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti); // GreeneryColor - m_engine->ChangeTextureColor("textures/objects/plant.png", COLOR_REF_GREEN, m_colorNewGreen, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti); + //m_engine->ChangeTextureColor("textures/objects/plant.png", COLOR_REF_GREEN, m_colorNewGreen, colorRef2, colorNew2, 0.50f, -1.0f, ts, ti); // water color // PARTIPLOUF0 and PARTIDROP : ts = { 0.500f, 0.500f }; ti = { 0.875f, 0.750f }; - m_engine->ChangeTextureColor("textures/effect00.png", COLOR_REF_WATER, m_colorNewWater, colorRef2, colorNew2, 0.20f, -1.0f, ts, ti, nullptr, m_colorShiftWater, true); + //m_engine->ChangeTextureColor("textures/effect00.png", COLOR_REF_WATER, m_colorNewWater, colorRef2, colorNew2, 0.20f, -1.0f, ts, ti, nullptr, m_colorShiftWater, true); // PARTIFLIC : ts = { 0.00f, 0.75f }; ti = { 0.25f, 1.00f }; - m_engine->ChangeTextureColor("textures/effect02.png", COLOR_REF_WATER, m_colorNewWater, colorRef2, colorNew2, 0.20f, -1.0f, ts, ti, nullptr, m_colorShiftWater, true); + //m_engine->ChangeTextureColor("textures/effect02.png", COLOR_REF_WATER, m_colorNewWater, colorRef2, colorNew2, 0.20f, -1.0f, ts, ti, nullptr, m_colorShiftWater, true); } //! Calculates the distance to the nearest object diff --git a/src/object/auto/autoportico.cpp b/src/object/auto/autoportico.cpp index a3383284..f1611011 100644 --- a/src/object/auto/autoportico.cpp +++ b/src/object/auto/autoportico.cpp @@ -400,9 +400,9 @@ void CAutoPortico::UpdateTrackMapping(float left, float right) left = left - std::floor(left); right = right - std::floor(right); - m_engine->SetUVTransform(rank, Gfx::ENG_RSTATE_PART1, + m_engine->SetUVTransform(rank, "tracker_right", { (1.0f - right) * scale, 0.0f }, { 1.0f, 1.0f }); - m_engine->SetUVTransform(rank, Gfx::ENG_RSTATE_PART2, + m_engine->SetUVTransform(rank, "tracker_left", { (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 62773318..180b11f7 100644 --- a/src/object/motion/motionvehicle.cpp +++ b/src/object/motion/motionvehicle.cpp @@ -1991,18 +1991,18 @@ void CMotionVehicle::UpdateTrackMapping(float left, float right, ObjectType type if (type == OBJECT_MOBILEdr) { - m_engine->SetUVTransform(rRank, Gfx::ENG_RSTATE_PART1, + m_engine->SetUVTransform(rRank, "tracker_right", { (1.0f - right) * scale, 0.0f }, { 1.0f, 1.0f }); - m_engine->SetUVTransform(lRank, Gfx::ENG_RSTATE_PART2, + m_engine->SetUVTransform(lRank, "tracker_left", { (1.0f - left) * scale, 0.0f }, { 1.0f, 1.0f }); } else { - m_engine->SetUVTransform(rRank, Gfx::ENG_RSTATE_PART1, + m_engine->SetUVTransform(rRank, "tracker_right", { (1.0f - right) * scale, 0.0f }, { 1.0f, 1.0f }); - m_engine->SetUVTransform(lRank, Gfx::ENG_RSTATE_PART2, + m_engine->SetUVTransform(lRank, "tracker_left", { (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 03345b58..1a3bd7de 100644 --- a/src/object/old_object.cpp +++ b/src/object/old_object.cpp @@ -2153,7 +2153,7 @@ void COldObject::UpdateEnergyMapping() std::string teamStr = StrUtils::ToString(GetTeam()); if(GetTeam() == 0) teamStr = ""; - m_engine->SetUVTransform(m_objectPart[0].object, Gfx::ENG_RSTATE_PART3, + m_engine->SetUVTransform(m_objectPart[0].object, "energy", { 0.0f, 0.25f * (GetEnergyLevel() - 1.0f) }, { 1.0f, 1.0f }); } diff --git a/src/ui/controls/control.cpp b/src/ui/controls/control.cpp index 7689b0dc..8d3c857e 100644 --- a/src/ui/controls/control.cpp +++ b/src/ui/controls/control.cpp @@ -522,7 +522,6 @@ void CControl::Draw() icon = SetButtonTextureForIcon(m_icon); renderer->SetTransparency(Gfx::TransparencyMode::WHITE); - //m_engine->SetState(Gfx::ENG_RSTATE_TTEXTURE_WHITE); if ( icon != -1 ) { DrawPart(icon, zoomInt, 0.0f);