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
dev
Tomasz Kapuściński 2022-02-13 00:03:46 +01:00
parent 0d612b9928
commit c378009128
16 changed files with 346 additions and 639 deletions

View File

@ -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

View File

@ -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

View File

@ -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
};
}

View File

@ -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<int>( 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<int>( 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<int>( 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<int>( 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<int>(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<int>( p1.next.size() ); l2++)
for (auto& data : p1.next)
{
EngineBaseObjTexTier& p2 = p1.next[l2];
for (int l3 = 0; l3 < static_cast<int>( 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<int>( 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<int>( p1.next.size() ); l2++)
for (auto& data : object.next)
{
EngineBaseObjTexTier& p2 = p1.next[l2];
for (int l3 = 0; l3 < static_cast<int>( 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<int>( p1.next.size() ); l2++)
for (auto& data : p1.next)
{
EngineBaseObjTexTier& p2 = p1.next[l2];
for (int l3 = 0; l3 < static_cast<int>( 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<Vertex3D>& vertices,
int state, std::string tex1Name, std::string tex2Name)
const Material& material, EngineTriangleType type)
{
assert(baseObjRank >= 0 && baseObjRank < static_cast<int>( 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<int>( 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<Vertex3D>&
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<int>( 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<int>( 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<int>( m_objects.size() ));
@ -859,9 +794,10 @@ void CEngine::DebugObject(int objRank)
for (int l2 = 0; l2 < static_cast<int>( 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<int>( m_objects.size() ));
int baseObjRank = m_objects[objRank].baseObjRank;
if (baseObjRank == -1)
return nullptr;
assert(baseObjRank >= 0 && baseObjRank < static_cast<int>( m_baseObjects.size() ));
EngineBaseObject& p1 = m_baseObjects[baseObjRank];
for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
{
EngineBaseObjTexTier& p2 = p1.next[l2];
if (p2.tex1Name != tex1Name)
continue;
for (int l3 = 0; l3 < static_cast<int>( 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<EngineTriangle>& triangles)
{
@ -1073,57 +976,48 @@ int CEngine::GetPartialTriangles(int objRank, float percent, int maxCount,
for (int l2 = 0; l2 < static_cast<int>( p1.next.size() ); l2++)
{
EngineBaseObjTexTier& p2 = p1.next[l2];
EngineBaseObjDataTier& p3 = p1.next[l2];
for (int l3 = 0; l3 < static_cast<int>( 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<int>( p3.vertices.size() ); i += 3)
{
if (static_cast<float>(actualCount) / total >= percent)
break;
if (static_cast<float>(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<int>( p3.vertices.size() ); i += 1)
{
if (static_cast<float>(actualCount) / total >= percent)
break;
if (static_cast<float>(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<int>( 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<int>(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<int>( 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<int>( p1.next.size() ); l2++)
for (auto& data : object.next)
{
EngineBaseObjTexTier& p2 = p1.next[l2];
for (int l3 = 0; l3 < static_cast<int>( p2.next.size() ); l3++)
for (const auto& vertex : data.vertices)
{
EngineBaseObjDataTier& p3 = p2.next[l3];
for (int i = 0; i < static_cast<int>( 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<int>( 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<int>( p1.next.size() ); l2++)
for (auto& data : object.next)
{
EngineBaseObjTexTier& p2 = p1.next[l2];
for (int l3 = 0; l3 < static_cast<int>( 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<int>( p1.next.size() ); l2++)
{
EngineBaseObjTexTier& p2 = p1.next[l2];
EngineBaseObjDataTier& data = p1.next[l2];
for (int l3 = 0; l3 < static_cast<int>( 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<int>(data.vertices.size()); i += 3)
{
for (int i = 0; i < static_cast<int>( 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<int>(data.vertices.size()) - 2; i += 1)
{
for (int i = 0; i < static_cast<int>( 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<int>( 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<int>( 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<int>( 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<int>( 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<int>( 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<int>( 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<int>( 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<int>(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<int>(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<int>( 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<int>( 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<Gfx::ModelTriangle>& triangles)
{
std::vector<Vertex3D> vs(3, Vertex3D{});
EngineBaseObject& p1 = m_baseObjects[baseObjRank];
std::array<Vertex3D, 3> 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<int>( m_objects.size() ));

View File

@ -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<Vertex3D> 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<EngineBaseObjDataTier> 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<EngineBaseObjTexTier> next;
//! Next tier
std::vector<EngineBaseObjDataTier> 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<Gfx::ModelTriangle>& triangles);
void AddBaseObjTriangles(int baseObjRank, const std::vector<Gfx::ModelTriangle>& 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<Vertex3D>& 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<EngineTriangle>& 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 &params, CImage* image = nullptr);
@ -1247,11 +1155,6 @@ protected:
//! Updates static buffers of changed objects
void UpdateStaticBuffers();
void AddBaseObjTriangles(int baseObjRank, const std::vector<Vertex3D>& vertices,
int state, std::string tex1Name, std::string tex2Name);
int GetEngineState(const ModelTriangle& triangle);
struct WriteScreenShotData
{
std::unique_ptr<CImage> img;

View File

@ -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<ModelTriangle>& triangles, int
triangles[i].tex1Name == "drawer.png" ||
triangles[i].tex1Name == "subm.png" )
{
triangles[i].tex1Name += StrUtils::ToString<int>(variant);
//triangles[i].tex1Name += StrUtils::ToString<int>(variant);
}
}
}

View File

@ -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);

View File

@ -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<Gfx::Vertex3D> 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);
}
}
}

View File

@ -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<int>(ModelRenderState::Alpha)) != 0)
triangle.transparentMode = ModelTransparentMode::AlphaChannel;
else if ((state & static_cast<int>(ModelRenderState::TTextureBlack)) != 0)
triangle.transparentMode = ModelTransparentMode::MapBlackToAlpha;
else if ((state & static_cast<int>(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<int>(ModelRenderState::Part1)) != 0)
triangle.specialMark = ModelSpecialMark::Part1;
triangle.tag = "tracker_right";
else if ((state & static_cast<int>(ModelRenderState::Part2)) != 0)
triangle.specialMark = ModelSpecialMark::Part2;
triangle.tag = "tracker_left";
else if ((state & static_cast<int>(ModelRenderState::Part3)) != 0)
triangle.specialMark = ModelSpecialMark::Part3;
triangle.tag = "energy";
else
triangle.specialMark = ModelSpecialMark::None;
triangle.tag = "";
triangle.doubleSided = (state & static_cast<int>(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 + "'");
}

View File

@ -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

View File

@ -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

View File

@ -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<int>(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

View File

@ -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 });
}

View File

@ -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 });
}
}

View File

@ -2153,7 +2153,7 @@ void COldObject::UpdateEnergyMapping()
std::string teamStr = StrUtils::ToString<int>(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 });
}

View File

@ -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);