Added UV transform and rewritten animated texture mapping code to use it

dev
Tomasz Kapuściński 2022-02-02 18:13:21 +01:00
parent 3bd4fee844
commit 7d9badb542
9 changed files with 79 additions and 205 deletions

View File

@ -174,6 +174,9 @@ public:
//! Sets transparency mode
virtual void SetTransparency(TransparencyMode mode) = 0;
//! Sets UV transform
virtual void SetUVTransform(const glm::vec2& offset, const glm::vec2& scale) = 0;
virtual void SetPrimaryTextureEnabled(bool enabled) = 0;
//! Sets triplanar mode
virtual void SetTriplanarMode(bool enabled) = 0;

View File

@ -640,7 +640,7 @@ EngineBaseObjDataTier& CEngine::AddLevel3(EngineBaseObjTexTier& p3, EngineTriang
return p3.next[i];
}
p3.next.push_back(EngineBaseObjDataTier(type, state));
p3.next.push_back(EngineBaseObjDataTier{ type, state });
return p3.next.back();
}
@ -1162,168 +1162,35 @@ void CEngine::ChangeSecondTexture(int objRank, const std::string& tex2Name)
}
}
void CEngine::ChangeTextureMapping(int objRank, int state,
const std::string& tex1Name, const std::string& tex2Name,
EngineTextureMapping mode,
float au, float bu, float av, float bv)
void CEngine::SetUVTransform(int objRank, int state, const glm::vec2& offset, const glm::vec2& scale)
{
assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
assert(objRank >= 0 && objRank < static_cast<int>(m_objects.size()));
EngineBaseObjDataTier* p4 = FindTriangles(objRank, state, tex1Name, tex2Name);
if (p4 == nullptr)
int baseObjRank = m_objects[objRank].baseObjRank;
if (baseObjRank == -1)
return;
int nb = p4->vertices.size();
assert(baseObjRank >= 0 && baseObjRank < static_cast<int>(m_baseObjects.size()));
if (mode == EngineTextureMapping::X)
{
for (int i = 0; i < nb; i++)
{
p4->vertices[i].uv.x = p4->vertices[i].position.z * au + bu;
p4->vertices[i].uv.y = p4->vertices[i].position.y * av + bv;
}
}
else if (mode == EngineTextureMapping::Y)
{
for (int i = 0; i < nb; i++)
{
p4->vertices[i].uv.x = p4->vertices[i].position.x * au + bu;
p4->vertices[i].uv.y = p4->vertices[i].position.z * av + bv;
}
}
else if (mode == EngineTextureMapping::Z)
{
for (int i = 0; i < nb; i++)
{
p4->vertices[i].uv.x = p4->vertices[i].position.x * au + bu;
p4->vertices[i].uv.y = p4->vertices[i].position.y * av + bv;
}
}
else if (mode == EngineTextureMapping::ONE_X)
{
for (int i = 0; i < nb; i++)
{
p4->vertices[i].uv.x = p4->vertices[i].position.x * au + bu;
}
}
else if (mode == EngineTextureMapping::ONE_Y)
{
for (int i = 0; i < nb; i++)
{
p4->vertices[i].uv.y = p4->vertices[i].position.y * au + bu;
}
}
else if (mode == EngineTextureMapping::ONE_Z)
{
for (int i = 0; i < nb; i++)
{
p4->vertices[i].uv.x = p4->vertices[i].position.z * au + bu;
}
}
EngineBaseObject& p1 = m_baseObjects[baseObjRank];
UpdateStaticBuffer(*p4);
for (size_t l2 = 0; l2 < p1.next.size(); l2++)
{
EngineBaseObjTexTier& p2 = p1.next[l2];
for (size_t l3 = 0; l3 < p2.next.size(); l3++)
{
EngineBaseObjDataTier& p3 = p2.next[l3];
if (p3.state & state)
{
p3.uvOffset = offset;
p3.uvScale = scale;
}
}
}
}
void CEngine::TrackTextureMapping(int objRank, int state,
const std::string& tex1Name, const std::string& tex2Name,
EngineTextureMapping mode,
float pos, float factor, float tl, float ts, float tt)
{
assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
EngineBaseObjDataTier* p4 = FindTriangles(objRank, state, tex1Name, tex2Name);
if (p4 == nullptr)
return;
int tNum = p4->vertices.size();
if (tNum < 12 || tNum % 6 != 0)
return;
std::vector<Gfx::Vertex3D>& vs = p4->vertices;
while (pos < 0.0f)
pos += 1.0f; // never negative!
glm::vec3 current{ 0, 0, 0 };
for (int i = 0; i < 6; i++)
{
for (int j = 0; j < 6; j++)
{
if (Math::IsEqual(vs[i].position.x, vs[j+6].position.x) &&
Math::IsEqual(vs[i].position.y, vs[j+6].position.y))
{
current.x = vs[i].position.x; // position end link
current.y = vs[i].position.y;
break;
}
}
}
float ps = 0.0f; // start position on the periphery
float pe = 0.0f;
int is[6] = { 0 }, ie[6] = { 0 };
int tBase = 0;
for (int ti = 0; ti < tNum / 6; ti++)
{
int s = 0;
int e = 0;
for (int i = 0; i < 6; i++)
{
if (Math::IsEqual(vs[tBase + i].position.x, current.x, 0.0001f) &&
Math::IsEqual(vs[tBase + i].position.y, current.y, 0.0001f))
{
ie[e++] = i;
}
else
{
is[s++] = i;
}
}
if (s == 3 && e == 3)
{
glm::vec2 endPosition{};
endPosition.x = vs[tBase + is[0]].position.x - vs[tBase + ie[0]].position.x;
endPosition.y = vs[tBase + is[0]].position.y - vs[tBase + ie[0]].position.y;
pe = ps + glm::length(endPosition) / factor; // end position on the periphery
float pps = ps + pos;
float ppe = pe + pos;
int offset = static_cast<int>(pps);
ppe -= offset;
pps -= offset;
for (int i = 0; i < 3; i++)
{
vs[tBase + is[i]].uv.x = ((pps * tl) + ts) / tt;
vs[tBase + ie[i]].uv.x = ((ppe * tl) + ts) / tt;
}
}
if (ti >= (tNum / 6) - 1)
break;
for (int i = 0; i < 6; i++)
{
if (!Math::IsEqual(vs[tBase + i+6].position.x, current.x, 0.0001f) ||
!Math::IsEqual(vs[tBase + i+6].position.y, current.y, 0.0001f))
{
current.x = vs[tBase + i+6].position.x; // end next link
current.y = vs[tBase + i+6].position.y;
break;
}
}
ps = pe; // following start position on the periphery
tBase += 6;
}
UpdateStaticBuffer(*p4);
}
void CEngine::CreateShadowSpot(int objRank)
{
assert(objRank >= 0 && objRank < static_cast<int>( m_objects.size() ));
@ -3570,6 +3437,7 @@ void CEngine::Draw3DScene()
objectRenderer->SetDirty(dirty);
objectRenderer->SetColor({ 1.0f, 1.0f, 1.0f, 1.0f });
objectRenderer->SetCullMode((p3.state& ENG_RSTATE_2FACE) == 0);
objectRenderer->SetUVTransform(p3.uvOffset, p3.uvScale);
objectRenderer->DrawObject(p3.buffer);
}
}
@ -3635,6 +3503,7 @@ void CEngine::Draw3DScene()
float dirty = (p3.state & ENG_RSTATE_DUAL_BLACK) && m_dirty ? 1.0 : 0.0;
objectRenderer->SetDirty(dirty);
objectRenderer->SetColor(tColor);
objectRenderer->SetUVTransform(p3.uvOffset, p3.uvScale);
objectRenderer->DrawObject(p3.buffer);
}
}

View File

@ -189,19 +189,13 @@ enum EngineObjectType
*/
struct EngineBaseObjDataTier
{
EngineTriangleType type;
int state;
EngineTriangleType type = EngineTriangleType::TRIANGLES;
int state = ENG_RSTATE_NORMAL;
std::vector<Vertex3D> vertices;
CVertexBuffer* buffer;
bool updateStaticBuffer;
inline EngineBaseObjDataTier(EngineTriangleType type = EngineTriangleType::TRIANGLES,
int state = ENG_RSTATE_NORMAL)
: type(type)
, state(state)
, buffer(nullptr)
, updateStaticBuffer(false)
{}
CVertexBuffer* buffer = nullptr;
bool updateStaticBuffer = false;
glm::vec2 uvOffset = { 0.0f, 0.0f };
glm::vec2 uvScale = { 1.0f, 1.0f };
};
/**
@ -785,17 +779,7 @@ public:
//! Changes the 2nd texure for given object
void ChangeSecondTexture(int objRank, const std::string& tex2Name);
//! Changes (recalculates) texture mapping for given object
void ChangeTextureMapping(int objRank, int state,
const std::string& tex1Name, const std::string& tex2Name,
EngineTextureMapping mode,
float au, float bu, float av, float bv);
//! Changes texture mapping for robot tracks
void TrackTextureMapping(int objRank, int state,
const std::string& tex1Name, const std::string& tex2Name,
EngineTextureMapping mode,
float pos, float factor, float tl, float ts, float tt);
void SetUVTransform(int objRank, int state, const glm::vec2& offset, const glm::vec2& scale);
//! Detects the target object that is selected with the mouse
/** Returns the rank of the object or -1. */

View File

@ -86,6 +86,8 @@ CGL33ObjectRenderer::CGL33ObjectRenderer(CGL33Device* device)
m_triplanarScale = glGetUniformLocation(m_program, "uni_TriplanarScale");
m_dirty = glGetUniformLocation(m_program, "uni_Dirty");
m_alphaScissor = glGetUniformLocation(m_program, "uni_AlphaScissor");
m_uvOffset = glGetUniformLocation(m_program, "uni_UVOffset");
m_uvScale = glGetUniformLocation(m_program, "uni_UVScale");
m_shadowRegions = glGetUniformLocation(m_program, "uni_ShadowRegions");
@ -174,6 +176,8 @@ void CGL33ObjectRenderer::CGL33ObjectRenderer::Begin()
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
SetUVTransform({ 0.0f, 0.0f }, { 1.0f, 1.0f });
}
void CGL33ObjectRenderer::CGL33ObjectRenderer::End()
@ -349,6 +353,12 @@ void CGL33ObjectRenderer::SetTransparency(TransparencyMode mode)
}
}
void CGL33ObjectRenderer::SetUVTransform(const glm::vec2& offset, const glm::vec2& scale)
{
glUniform2fv(m_uvOffset, 1, glm::value_ptr(offset));
glUniform2fv(m_uvScale, 1, glm::value_ptr(scale));
}
void CGL33ObjectRenderer::SetPrimaryTextureEnabled(bool enabled)
{
glUniform1f(m_primaryEnabled, enabled ? 1.0f : 0.0f);

View File

@ -83,6 +83,10 @@ public:
virtual void SetCullMode(bool enabled) override;
//! Sets transparency mode
virtual void SetTransparency(TransparencyMode mode) override;
//! Sets UV transform
virtual void SetUVTransform(const glm::vec2& offset, const glm::vec2& scale) override;
virtual void SetPrimaryTextureEnabled(bool enabled) override;
//! Sets triplanar mode
@ -119,6 +123,8 @@ private:
GLint m_triplanarScale = -1;
GLint m_dirty = -1;
GLint m_alphaScissor = -1;
GLint m_uvOffset = -1;
GLint m_uvScale = -1;
struct ShadowUniforms
{

View File

@ -24,6 +24,9 @@ uniform mat4 uni_ViewMatrix;
uniform mat4 uni_ModelMatrix;
uniform mat3 uni_NormalMatrix;
uniform vec2 uni_UVOffset;
uniform vec2 uni_UVScale;
layout(location = 0) in vec4 in_VertexCoord;
layout(location = 1) in vec3 in_Normal;
layout(location = 2) in vec4 in_Color;
@ -49,7 +52,7 @@ void main()
gl_Position = uni_ProjectionMatrix * eyeSpace;
data.Color = in_Color;
data.TexCoord0 = in_TexCoord0;
data.TexCoord0 = in_TexCoord0 * uni_UVScale + uni_UVOffset;
data.TexCoord1 = in_TexCoord1;
data.Normal = mat3(uni_NormalMatrix) * in_Normal;
data.VertexCoord = in_VertexCoord.xyz;

View File

@ -395,14 +395,14 @@ void CAutoPortico::UpdateTrackMapping(float left, float right)
{
int rank = m_object->GetObjectRank(0);
std::string teamStr = StrUtils::ToString<int>(m_object->GetTeam());
if(m_object->GetTeam() == 0) teamStr = "";
constexpr float scale = 0.25f / 8.0f;
m_engine->TrackTextureMapping(rank, Gfx::ENG_RSTATE_PART1, "objects/lemt.png"+teamStr, "",
Gfx::EngineTextureMapping::X,
right, 8.0f, 8.0f, 192.0f, 256.0f);
left = left - std::floor(left);
right = right - std::floor(right);
m_engine->TrackTextureMapping(rank, Gfx::ENG_RSTATE_PART2, "objects/lemt.png"+teamStr, "",
Gfx::EngineTextureMapping::X,
left, 8.0f, 8.0f, 192.0f, 256.0f);
m_engine->SetUVTransform(rank, Gfx::ENG_RSTATE_PART1,
{ (1.0f - right) * scale, 0.0f }, { 1.0f, 1.0f });
m_engine->SetUVTransform(rank, Gfx::ENG_RSTATE_PART2,
{ (1.0f - left) * scale, 0.0f }, { 1.0f, 1.0f });
}

View File

@ -1984,25 +1984,25 @@ void CMotionVehicle::UpdateTrackMapping(float left, float right, ObjectType type
std::string teamStr = StrUtils::ToString<int>(m_object->GetTeam());
if(m_object->GetTeam() == 0) teamStr = "";
constexpr float scale = 0.25f / 8.0f;
left = left - std::floor(left);
right = right - std::floor(right);
if (type == OBJECT_MOBILEdr)
{
m_engine->TrackTextureMapping(rRank, Gfx::ENG_RSTATE_PART1, "objects/drawer.png"+teamStr, "",
Gfx::EngineTextureMapping::X,
right, 1.0f, 8.0f, 192.0f, 256.0f);
m_engine->SetUVTransform(rRank, Gfx::ENG_RSTATE_PART1,
{ (1.0f - right) * scale, 0.0f }, { 1.0f, 1.0f });
m_engine->TrackTextureMapping(lRank, Gfx::ENG_RSTATE_PART2, "objects/drawer.png"+teamStr, "",
Gfx::EngineTextureMapping::X,
left, 1.0f, 8.0f, 192.0f, 256.0f);
m_engine->SetUVTransform(lRank, Gfx::ENG_RSTATE_PART2,
{ (1.0f - left) * scale, 0.0f }, { 1.0f, 1.0f });
}
else
{
m_engine->TrackTextureMapping(rRank, Gfx::ENG_RSTATE_PART1, "objects/lemt.png"+teamStr, "",
Gfx::EngineTextureMapping::X,
right, 1.0f, 8.0f, 192.0f, 256.0f);
m_engine->SetUVTransform(rRank, Gfx::ENG_RSTATE_PART1,
{ (1.0f - right) * scale, 0.0f }, { 1.0f, 1.0f });
m_engine->TrackTextureMapping(lRank, Gfx::ENG_RSTATE_PART2, "objects/lemt.png"+teamStr, "",
Gfx::EngineTextureMapping::X,
left, 1.0f, 8.0f, 192.0f, 256.0f);
m_engine->SetUVTransform(lRank, Gfx::ENG_RSTATE_PART2,
{ (1.0f - left) * scale, 0.0f }, { 1.0f, 1.0f });
}
}

View File

@ -2120,7 +2120,7 @@ void COldObject::FlatParent()
void COldObject::UpdateEnergyMapping()
{
if (Math::IsEqual(GetEnergyLevel(), m_lastEnergy, 0.01f))
if (m_lastEnergy == GetEnergyLevel())
return;
m_lastEnergy = GetEnergyLevel();
@ -2152,10 +2152,9 @@ void COldObject::UpdateEnergyMapping()
std::string teamStr = StrUtils::ToString<int>(GetTeam());
if(GetTeam() == 0) teamStr = "";
m_engine->ChangeTextureMapping(m_objectPart[0].object,
Gfx::ENG_RSTATE_PART3, "objects/lemt.png"+teamStr, "",
Gfx::EngineTextureMapping::ONE_Y,
au, bu, 1.0f, 0.0f);
m_engine->SetUVTransform(m_objectPart[0].object, Gfx::ENG_RSTATE_PART3,
{ 0.0f, 0.25f * (GetEnergyLevel() - 1.0f) }, { 1.0f, 1.0f });
}