diff --git a/src/graphics/core/device.h b/src/graphics/core/device.h index 38bc4638..4c1189c6 100644 --- a/src/graphics/core/device.h +++ b/src/graphics/core/device.h @@ -240,6 +240,9 @@ public: //! Provides a hook to debug graphics code (implementation-specific) virtual void DebugHook() = 0; + //! Displays light positions to aid in debuggings + virtual void DebugLights() = 0; + //! Initializes the device, setting the initial state virtual bool Create() = 0; //! Destroys the device, releasing every acquired resource diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index 3423864c..669ea425 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -128,6 +128,9 @@ CEngine::CEngine(CApplication *app) m_interfaceMode = false; + m_debugLights = false; + m_debugDumpLights = false; + m_mice[ENG_MOUSE_NORM] = EngineMouse( 0, 1, 32, ENG_RSTATE_TTEXTURE_WHITE, ENG_RSTATE_TTEXTURE_BLACK, Math::Point( 1.0f, 1.0f)); m_mice[ENG_MOUSE_WAIT] = EngineMouse( 2, 3, 33, ENG_RSTATE_TTEXTURE_WHITE, ENG_RSTATE_TTEXTURE_BLACK, Math::Point( 8.0f, 12.0f)); m_mice[ENG_MOUSE_HAND] = EngineMouse( 4, 5, 34, ENG_RSTATE_TTEXTURE_WHITE, ENG_RSTATE_TTEXTURE_BLACK, Math::Point( 7.0f, 2.0f)); @@ -325,7 +328,22 @@ bool CEngine::ProcessEvent(const Event &event) if (event.type == EVENT_KEY_DOWN) { if (event.key.key == KEY(F12)) + { m_showStats = !m_showStats; + return false; + } + + if (event.key.key == KEY(F11)) + { + m_debugLights = !m_debugLights; + return false; + } + + if (event.key.key == KEY(F10)) + { + m_debugDumpLights = true; + return false; + } } // By default, pass on all events @@ -3293,6 +3311,15 @@ void CEngine::Draw3DScene() m_lightMan->UpdateDeviceLights(ENG_OBJTYPE_TERRAIN); + if (m_debugLights) + m_device->DebugLights(); + + if (m_debugDumpLights) + { + m_debugDumpLights = false; + m_lightMan->DebugDumpLights(); + } + if (m_waterMode) { m_app->StartPerformanceCounter(PCNT_RENDER_WATER); diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index 207ae270..5ecde8fe 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -1437,6 +1437,9 @@ protected: //! True when drawing 2D UI bool m_interfaceMode; + + bool m_debugLights; + bool m_debugDumpLights; }; diff --git a/src/graphics/engine/lightman.cpp b/src/graphics/engine/lightman.cpp index cbb85099..3e512d83 100644 --- a/src/graphics/engine/lightman.cpp +++ b/src/graphics/engine/lightman.cpp @@ -71,6 +71,7 @@ void LightProgression::SetTarget(float value) DynamicLight::DynamicLight() { + rank = 0; used = enabled = false; priority = LIGHT_PRI_LOW; includeType = excludeType = ENG_OBJTYPE_NULL; @@ -98,6 +99,61 @@ void CLightManager::SetDevice(CDevice* device) m_lightMap = std::vector<int>(m_device->GetMaxLightCount(), -1); } +void CLightManager::DebugDumpLights() +{ + CLogger* l = GetLogger(); + + l->Debug("Dynamic lights:\n"); + + for (int i = 0; i < static_cast<int>( m_dynLights.size() ); ++i) + { + const DynamicLight& dynLight = m_dynLights[i]; + if (!dynLight.used) + continue; + + int deviceLight = -1; + for (int j = 0; j < m_lightMap.size(); ++j) + { + if (m_lightMap[j] == i) + { + deviceLight = j; + break; + } + } + + l->Debug(" light %d\n", i); + l->Debug(" enabled = %s\n", dynLight.enabled ? "true" : "false"); + l->Debug(" priority = %d\n", dynLight.priority); + l->Debug(" device light = %d\n", deviceLight); + l->Debug(" light:\n"); + + const Light& light = dynLight.light; + std::string str; + + l->Debug(" type = %d\n", light.type); + str = light.ambient.ToString(); + l->Debug(" ambient = %s\n", str.c_str()); + str = light.diffuse.ToString(); + l->Debug(" diffuse = %s\n", str.c_str()); + str = light.specular.ToString(); + l->Debug(" specular = %s\n", str.c_str()); + str = light.position.ToString(); + l->Debug(" position = %s\n", str.c_str()); + str = light.direction.ToString(); + l->Debug(" direction = %s\n", str.c_str()); + l->Debug(" attenuation0 = %s\n", light.attenuation0); + l->Debug(" attenuation1 = %s\n", light.attenuation1); + l->Debug(" attenuation2 = %s\n", light.attenuation2); + l->Debug(" spotAngle = %s\n", light.spotAngle); + l->Debug(" spotIntensity = %s\n", light.spotIntensity); + + l->Debug(" intensity: %f\n", dynLight.intensity.current); + l->Debug(" color: %f %f %f\n", dynLight.colorRed.current, dynLight.colorGreen.current, dynLight.colorBlue.current); + l->Debug(" includeType: %d\n", dynLight.includeType); + l->Debug(" excludeType: %d\n", dynLight.excludeType); + } +} + void CLightManager::FlushLights() { m_dynLights.clear(); @@ -117,6 +173,7 @@ int CLightManager::CreateLight(LightPriority priority) m_dynLights.push_back(DynamicLight()); m_dynLights[index] = DynamicLight(); + m_dynLights[index].rank = index; m_dynLights[index].used = true; m_dynLights[index].enabled = true; m_dynLights[index].priority = priority; @@ -411,7 +468,7 @@ void CLightManager::UpdateDeviceLights(EngineObjectType type) if (enabled) { - m_lightMap[lightMapIndex] = i; + m_lightMap[lightMapIndex] = sortedLights[i].rank; ++lightMapIndex; } @@ -424,8 +481,9 @@ void CLightManager::UpdateDeviceLights(EngineObjectType type) int rank = m_lightMap[i]; if (rank != -1) { - sortedLights[rank].light.ambient = Gfx::Color(0.2f, 0.2f, 0.2f); - m_device->SetLight(i, sortedLights[rank].light); + Light light = m_dynLights[rank].light; + light.ambient = Gfx::Color(0.2f, 0.2f, 0.2f); + m_device->SetLight(i, light); m_device->SetLightEnabled(i, true); } else diff --git a/src/graphics/engine/lightman.h b/src/graphics/engine/lightman.h index 171299c3..d0ac338d 100644 --- a/src/graphics/engine/lightman.h +++ b/src/graphics/engine/lightman.h @@ -84,6 +84,9 @@ enum LightPriority */ struct DynamicLight { + //! Rank (index) + int rank; + //! Whether the light is used bool used; //! Whether the light is turned on @@ -136,6 +139,9 @@ public: //! Sets the device to be used void SetDevice(CDevice* device); + //! Prints debug info + void DebugDumpLights(); + //! Clears and disables all lights void FlushLights(); //! Creates a new dynamic light and returns its index (lightRank) diff --git a/src/graphics/engine/pyro.cpp b/src/graphics/engine/pyro.cpp index 93198ece..7c518291 100644 --- a/src/graphics/engine/pyro.cpp +++ b/src/graphics/engine/pyro.cpp @@ -2398,6 +2398,7 @@ void CPyro::LightOperFrame(float rTime) { if ( m_progress < m_lightOper[i].progress ) { + assert(i > 0); // TODO: if assert fails, fix the code float progress = (m_progress-m_lightOper[i-1].progress) / (m_lightOper[i].progress-m_lightOper[i-1].progress); float intensity = m_lightOper[i-1].intensity + (m_lightOper[i].intensity-m_lightOper[i-1].intensity)*progress; diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp index 4bfc5428..534a13f2 100644 --- a/src/graphics/opengl/gldevice.cpp +++ b/src/graphics/opengl/gldevice.cpp @@ -79,6 +79,106 @@ void CGLDevice::DebugHook() glColor3i(0, 0, 0); } +void CGLDevice::DebugLights() +{ + Gfx::ColorHSV color(0.0, 1.0, 1.0); + + glLineWidth(3.0f); + glDisable(GL_LIGHTING); + glDepthMask(GL_FALSE); + glDisable(GL_BLEND); + + Math::Matrix saveWorldMat = m_worldMat; + m_worldMat.LoadIdentity(); + UpdateModelviewMatrix(); + + for (int i = 0; i < m_lights.size(); ++i) + { + color.h = static_cast<float>(i) / static_cast<float>(m_lights.size()); + if (m_lightsEnabled[i]) + { + const Light& l = m_lights[i]; + if (l.type == LIGHT_DIRECTIONAL) + { + Gfx::VertexCol v[2]; + v[0].coord = -Math::Normalize(l.direction) * 100.0f + Math::Vector(0.0f, 0.0f, 1.0f) * i; + v[0].color = HSV2RGB(color); + v[1].coord = Math::Normalize(l.direction) * 100.0f + Math::Vector(0.0f, 0.0f, 1.0f) * i; + v[1].color = HSV2RGB(color); + while (v[0].coord.y < 60.0f && v[0].coord.y < 60.0f) + { + v[0].coord.y += 10.0f; + v[1].coord.y += 10.0f; + } + DrawPrimitive(PRIMITIVE_LINES, v, 2); + + v[0].coord = v[1].coord + Math::Normalize(v[0].coord - v[1].coord) * 50.0f; + + glLineWidth(10.0f); + DrawPrimitive(PRIMITIVE_LINES, v, 2); + glLineWidth(3.0f); + } + else if (l.type == LIGHT_POINT) + { + Gfx::VertexCol v[8]; + for (int i = 0; i < 8; ++i) + v[i].color = HSV2RGB(color); + + v[0].coord = l.position + Math::Vector(-1.0f, -1.0f, -1.0f) * 4.0f; + v[1].coord = l.position + Math::Vector( 1.0f, -1.0f, -1.0f) * 4.0f; + v[2].coord = l.position + Math::Vector( 1.0f, 1.0f, -1.0f) * 4.0f; + v[3].coord = l.position + Math::Vector(-1.0f, 1.0f, -1.0f) * 4.0f; + v[4].coord = l.position + Math::Vector(-1.0f, -1.0f, -1.0f) * 4.0f; + DrawPrimitive(PRIMITIVE_LINE_STRIP, v, 5); + + v[0].coord = l.position + Math::Vector(-1.0f, -1.0f, 1.0f) * 4.0f; + v[1].coord = l.position + Math::Vector( 1.0f, -1.0f, 1.0f) * 4.0f; + v[2].coord = l.position + Math::Vector( 1.0f, 1.0f, 1.0f) * 4.0f; + v[3].coord = l.position + Math::Vector(-1.0f, 1.0f, 1.0f) * 4.0f; + v[4].coord = l.position + Math::Vector(-1.0f, -1.0f, 1.0f) * 4.0f; + DrawPrimitive(PRIMITIVE_LINE_STRIP, v, 5); + + v[0].coord = l.position + Math::Vector(-1.0f, -1.0f, -1.0f) * 4.0f; + v[1].coord = l.position + Math::Vector(-1.0f, -1.0f, 1.0f) * 4.0f; + v[2].coord = l.position + Math::Vector( 1.0f, -1.0f, -1.0f) * 4.0f; + v[3].coord = l.position + Math::Vector( 1.0f, -1.0f, 1.0f) * 4.0f; + v[4].coord = l.position + Math::Vector( 1.0f, 1.0f, -1.0f) * 4.0f; + v[5].coord = l.position + Math::Vector( 1.0f, 1.0f, 1.0f) * 4.0f; + v[6].coord = l.position + Math::Vector(-1.0f, 1.0f, -1.0f) * 4.0f; + v[7].coord = l.position + Math::Vector(-1.0f, 1.0f, 1.0f) * 4.0f; + DrawPrimitive(PRIMITIVE_LINES, v, 8); + } + else if (l.type == LIGHT_SPOT) + { + Gfx::VertexCol v[5]; + for (int i = 0; i < 5; ++i) + v[i].color = HSV2RGB(color); + + v[0].coord = l.position + Math::Vector(-1.0f, 0.0f, -1.0f) * 4.0f; + v[1].coord = l.position + Math::Vector( 1.0f, 0.0f, -1.0f) * 4.0f; + v[2].coord = l.position + Math::Vector( 1.0f, 0.0f, 1.0f) * 4.0f; + v[3].coord = l.position + Math::Vector(-1.0f, 0.0f, 1.0f) * 4.0f; + v[4].coord = l.position + Math::Vector(-1.0f, 0.0f, -1.0f) * 4.0f; + DrawPrimitive(PRIMITIVE_LINE_STRIP, v, 5); + + v[0].coord = l.position; + v[1].coord = l.position + Math::Normalize(l.direction) * 100.0f; + glEnable(GL_LINE_STIPPLE); + glLineStipple(3.0, 0xFF); + DrawPrimitive(PRIMITIVE_LINES, v, 2); + glDisable(GL_LINE_STIPPLE); + } + } + } + + glLineWidth(1.0f); + glEnable(GL_LIGHTING); + glDepthMask(GL_TRUE); + glEnable(GL_BLEND); + m_worldMat = saveWorldMat; + UpdateModelviewMatrix(); +} + bool CGLDevice::Create() { GetLogger()->Info("Creating CDevice\n"); diff --git a/src/graphics/opengl/gldevice.h b/src/graphics/opengl/gldevice.h index 004a18ba..c648161c 100644 --- a/src/graphics/opengl/gldevice.h +++ b/src/graphics/opengl/gldevice.h @@ -93,6 +93,7 @@ public: virtual ~CGLDevice(); virtual void DebugHook(); + virtual void DebugLights(); virtual bool Create(); virtual void Destroy(); diff --git a/src/math/matrix.h b/src/math/matrix.h index a13f8231..f139517a 100644 --- a/src/math/matrix.h +++ b/src/math/matrix.h @@ -97,8 +97,8 @@ struct Matrix //! Sets value in given row and col /** - * \param row row (0 to 3) - * \param col column (0 to 3) + * \param row row (1 to 4) + * \param col column (1 to 4) * \param value value */ inline void Set(int row, int col, float value) @@ -108,8 +108,8 @@ struct Matrix //! Returns the value in given row and col /** - * \param row row (0 to 3) - * \param col column (0 to 3) + * \param row row (1 to 4) + * \param col column (1 to 4) * \returns value */ inline float Get(int row, int col) diff --git a/test/envs/opengl/CMakeLists.txt b/test/envs/opengl/CMakeLists.txt index 0bcb43d5..c52b8b44 100644 --- a/test/envs/opengl/CMakeLists.txt +++ b/test/envs/opengl/CMakeLists.txt @@ -12,6 +12,7 @@ else() endif() set(TEXTURE_SOURCES +${SRC_DIR}/graphics/core/color.cpp ${SRC_DIR}/graphics/opengl/gldevice.cpp ${SRC_DIR}/common/logger.cpp ${SRC_DIR}/common/image.cpp @@ -19,6 +20,7 @@ texture_test.cpp ) set(MODEL_SOURCES +${SRC_DIR}/graphics/core/color.cpp ${SRC_DIR}/graphics/opengl/gldevice.cpp ${SRC_DIR}/graphics/engine/modelfile.cpp ${SRC_DIR}/common/logger.cpp @@ -30,6 +32,7 @@ model_test.cpp ) set(TRANSFORM_SOURCES +${SRC_DIR}/graphics/core/color.cpp ${SRC_DIR}/graphics/opengl/gldevice.cpp ${SRC_DIR}/common/logger.cpp ${SRC_DIR}/common/image.cpp @@ -39,6 +42,7 @@ transform_test.cpp ) set(LIGHT_SOURCES +${SRC_DIR}/graphics/core/color.cpp ${SRC_DIR}/graphics/opengl/gldevice.cpp ${SRC_DIR}/common/logger.cpp ${SRC_DIR}/common/image.cpp diff --git a/test/unit/graphics/core/device_mock.h b/test/unit/graphics/core/device_mock.h index 80e214fe..9e75daff 100644 --- a/test/unit/graphics/core/device_mock.h +++ b/test/unit/graphics/core/device_mock.h @@ -10,6 +10,7 @@ public: CDeviceMock() {} MOCK_METHOD0(DebugHook, void()); + MOCK_METHOD0(DebugLights, void()); MOCK_METHOD0(Create, bool()); MOCK_METHOD0(Destroy, void());