diff --git a/src/gx/gll/GLDevice.cpp b/src/gx/gll/GLDevice.cpp index 3a74e0c..8489cc4 100644 --- a/src/gx/gll/GLDevice.cpp +++ b/src/gx/gll/GLDevice.cpp @@ -628,8 +628,59 @@ void GLDevice::ApplyGLStates(const GLStates& states, bool force) { { glMatrixMode(GL_PROJECTION); - // TODO - // - some interesting logic to manipulate the projection matrix before loading + GLTransform projection = { + true, + { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f, + }, + true + }; + + if (!states.fixedFunc.transforms.projection.isIdentity) { + projection.isIdentity = false; + + memcpy(projection.m, states.fixedFunc.transforms.projection.m, sizeof(projection.m)); + projection.isDirty = true; + } + + if (projection.isIdentity) { + projection.SetIdentity(); + } + + projection.a1 *= -1.0f; + projection.b1 *= -1.0f; + projection.c1 *= -1.0f; + projection.d1 *= -1.0f; + + auto isIdentity = projection.a0 == 1.0f + && projection.a1 == 0.0f + && projection.a2 == 0.0f + && projection.a3 == 0.0f + && projection.b0 == 0.0f + && projection.b1 == 1.0f + && projection.b2 == 0.0f + && projection.b3 == 0.0f + && projection.c0 == 0.0f + && projection.c1 == 0.0f + && projection.c2 == 1.0f + && projection.c3 == 0.0f + && projection.d0 == 0.0f + && projection.d1 == 0.0f + && projection.d2 == 0.0f + && projection.d3 == 1.0f; + + projection.isDirty = true; + + if (isIdentity) { + glLoadIdentity(); + } else { + glLoadMatrixf(projection.m); + } + + projection.isDirty = false; } glMatrixMode(states.fixedFunc.transforms.matrixMode); @@ -892,7 +943,53 @@ void GLDevice::ApplyShaderConstants() { } void GLDevice::ApplyTransforms() { - // TODO + this->SetModelView(GL_MODELVIEW); + + auto& projection = this->m_States.fixedFunc.transforms.projection; + if (projection.isDirty) { + if (projection.isIdentity) { + projection.SetIdentity(); + } + + projection.a1 *= -1.0f; + projection.b1 *= -1.0f; + projection.c1 *= -1.0f; + projection.d1 *= -1.0f; + + projection.isIdentity = projection.a0 == 1.0f + && projection.a1 == 0.0f + && projection.a2 == 0.0f + && projection.a3 == 0.0f + && projection.b0 == 0.0f + && projection.b1 == 1.0f + && projection.b2 == 0.0f + && projection.b3 == 0.0f + && projection.c0 == 0.0f + && projection.c1 == 0.0f + && projection.c2 == 1.0f + && projection.c3 == 0.0f + && projection.d0 == 0.0f + && projection.d1 == 0.0f + && projection.d2 == 0.0f + && projection.d3 == 1.0f; + + projection.isDirty = true; + + if (this->m_States.fixedFunc.transforms.matrixMode != GL_PROJECTION) { + glMatrixMode(GL_PROJECTION); + this->m_States.fixedFunc.transforms.matrixMode = GL_PROJECTION; + } + + if (projection.isIdentity) { + glLoadIdentity(); + } else { + glLoadMatrixf(projection.m); + } + + projection.isDirty = false; + } + + // TODO texture transforms } void GLDevice::BindBuffer(GLBuffer* buffer, GLEnum target) { @@ -2315,6 +2412,57 @@ void GLDevice::SetLightingEnable(bool enable) { } } +void GLDevice::SetModelView(GLEnum transform) { + if (transform == 'VIEW') { + // TODO + return; + } + + if (transform == 'WRLD') { + // TODO + return; + } + + if (transform != GL_MODELVIEW) { + BLIZZARD_ASSERT(false); + } + + auto& world = this->m_States.fixedFunc.transforms.world; + auto& view = this->m_States.fixedFunc.transforms.view; + auto& modelView = this->m_States.fixedFunc.transforms.modelView; + + if (this->m_States.fixedFunc.transforms.modelviewStatus != transform || modelView.isDirty) { + if (world.isIdentity && view.isIdentity) { + modelView.isIdentity = true; + modelView.isDirty = true; + } else if (world.isIdentity) { + modelView = view; + modelView.isIdentity = false; + modelView.isDirty = true; + } else if (view.isIdentity) { + modelView = world; + modelView.isIdentity = false; + modelView.isDirty = true; + } else { + // TODO assign model * view to modelView + BLIZZARD_ASSERT(!"Unimplemented"); + } + + if (this->m_States.fixedFunc.transforms.matrixMode != GL_MODELVIEW) { + glMatrixMode(GL_MODELVIEW); + this->m_States.fixedFunc.transforms.matrixMode = GL_MODELVIEW; + } + + if (modelView.isIdentity) { + glLoadIdentity(); + } else { + glLoadMatrixf(modelView.m); + } + + this->m_States.fixedFunc.transforms.modelviewStatus = transform; + } +} + void GLDevice::SetScissor(bool a2, const GLRect& a3) { // TODO } @@ -2469,15 +2617,13 @@ void GLDevice::SetTransform(GLEnum transform, const float* a3) { BLIZZARD_ASSERT(false); } - // TODO - // int32_t needsUpdate = !(t == a3); // GLTransform::operator==() - // if (needsUpdate) { - // t.Set(a3); - // } + if (*t != a3) { + t->Set(a3); + } if (t->isDirty) { if (transform == 'VIEW' || transform == 'WRLD') { - this->m_States.fixedFunc.transforms.modelView.isDirty = 1; + this->m_States.fixedFunc.transforms.modelView.isDirty = true; } } } diff --git a/src/gx/gll/GLDevice.h b/src/gx/gll/GLDevice.h index df09376..c3f8e98 100644 --- a/src/gx/gll/GLDevice.h +++ b/src/gx/gll/GLDevice.h @@ -172,6 +172,7 @@ class GLDevice { void SetFogParam(GLEnum param, float value); void SetIndexBuffer(GLBuffer*); void SetLightingEnable(bool enable); + void SetModelView(GLEnum view); void SetScissor(bool, const GLRect&); void SetShader(GLShader::ShaderType, GLShader*); void SetShaderConstants(GLShader::ShaderType, uint32_t, const float*, uint32_t); diff --git a/src/gx/gll/GLTypes.cpp b/src/gx/gll/GLTypes.cpp index 6875344..226ae4f 100644 --- a/src/gx/gll/GLTypes.cpp +++ b/src/gx/gll/GLTypes.cpp @@ -1,5 +1,58 @@ #include "gx/gll/GLTypes.h" +#include GLColor4f GLColor4f::ZERO = { 0.0, 0.0, 0.0, 0.0 }; GLColor4f GLColor4f::WHITE = { 1.0, 1.0, 1.0, 1.0 }; GLColor4f GLColor4f::BLACK = { 0.0, 0.0, 0.0, 1.0 }; + +bool GLTransform::operator==(const float m[16]) const { + return this->m[0] == m[0] + && this->m[1] == m[1] + && this->m[2] == m[2] + && this->m[3] == m[3] + && this->m[4] == m[4] + && this->m[5] == m[5] + && this->m[6] == m[6] + && this->m[7] == m[7] + && this->m[8] == m[8] + && this->m[9] == m[9] + && this->m[10] == m[10] + && this->m[11] == m[11] + && this->m[12] == m[12] + && this->m[13] == m[13] + && this->m[14] == m[14] + && this->m[15] == m[15]; +} + +bool GLTransform::operator!=(const float m[16]) const { + return !(*this == m); +} + +void GLTransform::Set(const float m[16]) { + memcpy(this->m, m, sizeof(this->m)); + this->isDirty = true; + this->isIdentity = this->a0 == 1.0f + && this->a1 == 0.0f + && this->a2 == 0.0f + && this->a3 == 0.0f + && this->b0 == 0.0f + && this->b1 == 1.0f + && this->b2 == 0.0f + && this->b3 == 0.0f + && this->c0 == 0.0f + && this->c1 == 0.0f + && this->c2 == 1.0f + && this->c3 == 0.0f + && this->d0 == 0.0f + && this->d1 == 0.0f + && this->d2 == 0.0f + && this->d3 == 1.0f; +} + +void GLTransform::SetIdentity() { + memset(this->m, 0, sizeof(this->m)); + this->a0 = 1.0f; + this->b1 = 1.0f; + this->c2 = 1.0f; + this->d3 = 1.0f; +} diff --git a/src/gx/gll/GLTypes.h b/src/gx/gll/GLTypes.h index 6b01706..9c147fb 100644 --- a/src/gx/gll/GLTypes.h +++ b/src/gx/gll/GLTypes.h @@ -138,6 +138,11 @@ struct GLTransform { }; bool isIdentity; + + bool operator==(const float m[16]) const; + bool operator!=(const float m[16]) const; + void Set(const float m[16]); + void SetIdentity(); }; struct GLStates {