From 688315ab76145a32d0aebf826fbbb7fc9ce24443 Mon Sep 17 00:00:00 2001 From: Piotr Dziwinski Date: Sat, 20 Oct 2012 23:06:56 +0200 Subject: ComputeSphereVisibility and fixes in CEngine TODOs - view frustum culling with ComputeSphereVisibility - game should run faster now - resolved/removed most TODOs from CEngine - fixed OpenGL tests --- src/graphics/core/device.h | 29 +++++------ src/graphics/engine/engine.cpp | 60 ++++++++++++----------- src/graphics/engine/engine.h | 6 --- src/graphics/engine/water.cpp | 6 ++- src/graphics/opengl/gldevice.cpp | 80 +++++++++++++++++-------------- src/graphics/opengl/test/light_test.cpp | 27 ++++++++++- src/graphics/opengl/test/texture_test.cpp | 1 - 7 files changed, 122 insertions(+), 87 deletions(-) (limited to 'src') diff --git a/src/graphics/core/device.h b/src/graphics/core/device.h index b6dd138..8e7d446 100644 --- a/src/graphics/core/device.h +++ b/src/graphics/core/device.h @@ -204,22 +204,22 @@ enum PrimitiveType }; /** - * \enum IntersectPlane - * \brief Intersection plane of projection volume + * \enum FrustumPlane + * \brief Planes of frustum space * - * These flags can be OR'd together. + * Bitset of flags - can be OR'd together. */ -enum IntersectPlane +enum FrustumPlane { - INTERSECT_PLANE_LEFT = 0x01, - INTERSECT_PLANE_RIGHT = 0x02, - INTERSECT_PLANE_TOP = 0x04, - INTERSECT_PLANE_BOTTOM = 0x08, - INTERSECT_PLANE_FRONT = 0x10, - INTERSECT_PLANE_BACK = 0x20, - INTERSECT_PLANE_ALL = INTERSECT_PLANE_LEFT | INTERSECT_PLANE_RIGHT | - INTERSECT_PLANE_TOP | INTERSECT_PLANE_BOTTOM | - INTERSECT_PLANE_FRONT | INTERSECT_PLANE_BACK + FRUSTUM_PLANE_LEFT = 0x01, + FRUSTUM_PLANE_RIGHT = 0x02, + FRUSTUM_PLANE_TOP = 0x04, + FRUSTUM_PLANE_BOTTOM = 0x08, + FRUSTUM_PLANE_FRONT = 0x10, + FRUSTUM_PLANE_BACK = 0x20, + FRUSTUM_PLANE_ALL = FRUSTUM_PLANE_LEFT | FRUSTUM_PLANE_RIGHT | + FRUSTUM_PLANE_TOP | FRUSTUM_PLANE_BOTTOM | + FRUSTUM_PLANE_FRONT | FRUSTUM_PLANE_BACK }; /** @@ -316,7 +316,8 @@ public: //! Renders primitive composed of vertices with color information virtual void DrawPrimitive(PrimitiveType type, const VertexCol *vertices , int vertexCount) = 0; - //! Tests whether a sphere intersects the 6 clipping planes of projection volume + //! Tests whether a sphere is (partially) within the frustum volume + //! Returns a mask of frustum planes for which the test is positive virtual int ComputeSphereVisibility(const Math::Vector ¢er, float radius) = 0; //! Enables/disables the given render state diff --git a/src/graphics/engine/engine.cpp b/src/graphics/engine/engine.cpp index 019e959..ca10304 100644 --- a/src/graphics/engine/engine.cpp +++ b/src/graphics/engine/engine.cpp @@ -422,18 +422,6 @@ bool CEngine::WriteScreenShot(const std::string& fileName, int width, int height return true; } -bool CEngine::ReadSettings() -{ - // TODO: when INI reading is completed - return true; -} - -bool CEngine::WriteSettings() -{ - // TODO: when INI writing is completed - return true; -} - void CEngine::SetPause(bool pause) { m_pause = pause; @@ -966,7 +954,6 @@ EngineObjLevel4* CEngine::FindTriangles(int objRank, const Material& material, if (! p1.used) continue; if (p1.tex1Name != tex1Name) continue; - // TODO: tex2Name compare? for (int l2 = 0; l2 < static_cast( p1.next.size() ); l2++) { @@ -1557,7 +1544,22 @@ void CEngine::FlushGroundSpot() m_groundSpots.clear(); m_firstGroundSpot = true; - // TODO: blank all shadow textures + for (int s = 0; s < 16; s++) + { + CImage shadowImg(Math::IntPoint(256, 256)); + shadowImg.Fill(Gfx::IntColor(255, 255, 255, 255)); + + std::stringstream str; + str << "shadow" << std::setfill('0') << std::setw(2) << s << ".png"; + std::string texName = str.str(); + + DeleteTexture(texName); + + Gfx::Texture tex = m_device->CreateTexture(&shadowImg, m_defaultTexParams); + + m_texNameMap[texName] = tex; + m_revTexNameMap[tex] = texName; + } } int CEngine::CreateGroundSpot() @@ -1658,8 +1660,6 @@ void CEngine::DeleteGroundMark(int rank) void CEngine::ComputeDistance() { - // TODO: s_resol??? - for (int i = 0; i < static_cast( m_objects.size() ); i++) { if (! m_objects[i].used) @@ -1877,9 +1877,18 @@ bool CEngine::DetectTriangle(Math::Point mouse, VertexTex2* triangle, int objRan return true; } +//! Use only after world transform already set bool CEngine::IsVisible(int objRank) { - // TODO: use ComputeSphereVisiblity() after tested OK + float radius = m_objects[objRank].radius; + Math::Vector center(0.0f, 0.0f, 0.0f); + if (m_device->ComputeSphereVisibility(center, radius) == Gfx::FRUSTUM_PLANE_ALL) + { + m_objects[objRank].visible = true; + return true; + } + + m_objects[objRank].visible = false; return true; } @@ -1938,7 +1947,7 @@ void CEngine::SetState(int state, const Color& color) params.colorOperation = TEX_MIX_OPER_MODULATE; params.colorArg1 = TEX_MIX_ARG_TEXTURE; params.colorArg2 = TEX_MIX_ARG_FACTOR; - params.alphaOperation = TEX_MIX_OPER_DEFAULT; // TODO: replace with src color ? + params.alphaOperation = TEX_MIX_OPER_DEFAULT; params.factor = color; m_device->SetTextureEnabled(0, true); @@ -1957,7 +1966,7 @@ void CEngine::SetState(int state, const Color& color) params.colorOperation = TEX_MIX_OPER_ADD; params.colorArg1 = TEX_MIX_ARG_TEXTURE; params.colorArg2 = TEX_MIX_ARG_FACTOR; - params.alphaOperation = TEX_MIX_OPER_DEFAULT; // TODO: replace with src color ? + params.alphaOperation = TEX_MIX_OPER_DEFAULT; params.factor = color.Inverse(); m_device->SetTextureEnabled(0, true); @@ -1997,7 +2006,7 @@ void CEngine::SetState(int state, const Color& color) TextureStageParams params; params.colorOperation = TEX_MIX_OPER_REPLACE; params.colorArg1 = TEX_MIX_ARG_TEXTURE; - params.alphaOperation = TEX_MIX_OPER_DEFAULT; // TODO: replace with src color ? + params.alphaOperation = TEX_MIX_OPER_DEFAULT; m_device->SetTextureEnabled(0, true); m_device->SetTextureStageParams(0, params); @@ -2065,7 +2074,7 @@ void CEngine::SetState(int state, const Color& color) TextureStageParams params; params.colorOperation = TEX_MIX_OPER_DEFAULT; // default modulate - params.alphaOperation = TEX_MIX_OPER_DEFAULT; // TODO: replace with src color ? + params.alphaOperation = TEX_MIX_OPER_DEFAULT; m_device->SetTextureEnabled(0, true); m_device->SetTextureStageParams(0, params); @@ -2086,7 +2095,7 @@ void CEngine::SetState(int state, const Color& color) params.colorOperation = TEX_MIX_OPER_MODULATE; params.colorArg1 = TEX_MIX_ARG_TEXTURE; params.colorArg2 = TEX_MIX_ARG_COMPUTED_COLOR; - params.alphaOperation = TEX_MIX_OPER_DEFAULT; // TODO: ??? + params.alphaOperation = TEX_MIX_OPER_DEFAULT; m_device->SetTextureEnabled(1, true); m_device->SetTextureStageParams(1, params); } @@ -2096,7 +2105,7 @@ void CEngine::SetState(int state, const Color& color) params.colorOperation = TEX_MIX_OPER_ADD; params.colorArg1 = TEX_MIX_ARG_TEXTURE; params.colorArg2 = TEX_MIX_ARG_COMPUTED_COLOR; - params.alphaOperation = TEX_MIX_OPER_DEFAULT; // TODO: ??? + params.alphaOperation = TEX_MIX_OPER_DEFAULT; m_device->SetTextureEnabled(1, true); m_device->SetTextureStageParams(1, params); } @@ -4033,11 +4042,6 @@ void CEngine::DrawOverColor() SetState(m_overMode); - // TODO: set also with m_overMode ? - m_device->SetRenderState(RENDER_STATE_DEPTH_WRITE, false); - m_device->SetRenderState(RENDER_STATE_LIGHTING, false); - m_device->SetRenderState(RENDER_STATE_FOG, false); - m_device->SetTransform(TRANSFORM_VIEW, m_matViewInterface); m_device->SetTransform(TRANSFORM_PROJECTION, m_matProjInterface); m_device->SetTransform(TRANSFORM_WORLD, m_matWorldInterface); diff --git a/src/graphics/engine/engine.h b/src/graphics/engine/engine.h index 27f0173..d127e74 100644 --- a/src/graphics/engine/engine.h +++ b/src/graphics/engine/engine.h @@ -692,12 +692,6 @@ public: //! Writes a screenshot containing the current frame bool WriteScreenShot(const std::string& fileName, int width, int height); - - //! Reads settings from INI - bool ReadSettings(); - //! Writes settings to INI - bool WriteSettings(); - //@{ //! Management of game pause mode void SetPause(bool pause); diff --git a/src/graphics/engine/water.cpp b/src/graphics/engine/water.cpp index 18811eb..6c822b3 100644 --- a/src/graphics/engine/water.cpp +++ b/src/graphics/engine/water.cpp @@ -386,9 +386,11 @@ void CWater::DrawSurf() Math::Vector p = pos; p.x += size*(m_lines[i].len-1); float radius = sqrtf(powf(size, 2.0f)+powf(size*m_lines[i].len, 2.0f)); - if ( Math::Distance(p, eye) > deep+radius ) continue; + if (Math::Distance(p, eye) > deep + radius) + continue; - // TODO: ComputeSphereVisibility + if (device->ComputeSphereVisibility(p, radius) != Gfx::FRUSTUM_PLANE_ALL) + continue; int vertexIndex = 0; diff --git a/src/graphics/opengl/gldevice.cpp b/src/graphics/opengl/gldevice.cpp index 94b0dbc..a6ba1eb 100644 --- a/src/graphics/opengl/gldevice.cpp +++ b/src/graphics/opengl/gldevice.cpp @@ -929,27 +929,25 @@ void CGLDevice::DrawPrimitive(PrimitiveType type, const VertexCol *vertices, int bool InPlane(Math::Vector normal, float originPlane, Math::Vector center, float radius) { - float distance = (originPlane + Math::DotProduct(normal, center)) / normal.Length(); + float distance = originPlane + Math::DotProduct(normal, center); if (distance < -radius) - return true; + return false; - return false; + return true; } -/* - The implementation of ComputeSphereVisibility is taken from libwine's device.c - Copyright of the WINE team, licensed under GNU LGPL v 2.1 - */ +/* Based on libwine's implementation */ -// TODO: testing int CGLDevice::ComputeSphereVisibility(const Math::Vector ¢er, float radius) { Math::Matrix m; - m.LoadIdentity(); - m = Math::MultiplyMatrices(m, m_worldMat); - m = Math::MultiplyMatrices(m, m_viewMat); - m = Math::MultiplyMatrices(m, m_projectionMat); + m = Math::MultiplyMatrices(m_worldMat, m); + m = Math::MultiplyMatrices(m_viewMat, m); + Math::Matrix sc; + Math::LoadScaleMatrix(sc, Math::Vector(1.0f, 1.0f, -1.0f)); + m = Math::MultiplyMatrices(sc, m); + m = Math::MultiplyMatrices(m_projectionMat, m); Math::Vector vec[6]; float originPlane[6]; @@ -958,52 +956,64 @@ int CGLDevice::ComputeSphereVisibility(const Math::Vector ¢er, float radius) vec[0].x = m.Get(4, 1) + m.Get(1, 1); vec[0].y = m.Get(4, 2) + m.Get(1, 2); vec[0].z = m.Get(4, 3) + m.Get(1, 3); - originPlane[0] = m.Get(4, 4) + m.Get(1, 4); + float l1 = vec[0].Length(); + vec[0].Normalize(); + originPlane[0] = (m.Get(4, 4) + m.Get(1, 4)) / l1; // Right plane vec[1].x = m.Get(4, 1) - m.Get(1, 1); vec[1].y = m.Get(4, 2) - m.Get(1, 2); vec[1].z = m.Get(4, 3) - m.Get(1, 3); - originPlane[1] = m.Get(4, 4) - m.Get(1, 4); - - // Top plane - vec[2].x = m.Get(4, 1) - m.Get(2, 1); - vec[2].y = m.Get(4, 2) - m.Get(2, 2); - vec[2].z = m.Get(4, 3) - m.Get(2, 3); - originPlane[2] = m.Get(4, 4) - m.Get(2, 4); + float l2 = vec[1].Length(); + vec[1].Normalize(); + originPlane[1] = (m.Get(4, 4) - m.Get(1, 4)) / l2; // Bottom plane - vec[3].x = m.Get(4, 1) + m.Get(2, 1); - vec[3].y = m.Get(4, 2) + m.Get(2, 2); - vec[3].z = m.Get(4, 3) + m.Get(2, 3); - originPlane[3] = m.Get(4, 4) + m.Get(2, 4); + vec[2].x = m.Get(4, 1) + m.Get(2, 1); + vec[2].y = m.Get(4, 2) + m.Get(2, 2); + vec[2].z = m.Get(4, 3) + m.Get(2, 3); + float l3 = vec[2].Length(); + vec[2].Normalize(); + originPlane[2] = (m.Get(4, 4) + m.Get(2, 4)) / l3; + + // Top plane + vec[3].x = m.Get(4, 1) - m.Get(2, 1); + vec[3].y = m.Get(4, 2) - m.Get(2, 2); + vec[3].z = m.Get(4, 3) - m.Get(2, 3); + float l4 = vec[3].Length(); + vec[3].Normalize(); + originPlane[3] = (m.Get(4, 4) - m.Get(2, 4)) / l4; // Front plane - vec[4].x = m.Get(3, 1); - vec[4].y = m.Get(3, 2); - vec[4].z = m.Get(3, 3); - originPlane[4] = m.Get(3, 4); + vec[4].x = m.Get(4, 1) + m.Get(3, 1); + vec[4].y = m.Get(4, 2) + m.Get(3, 2); + vec[4].z = m.Get(4, 3) + m.Get(3, 3); + float l5 = vec[4].Length(); + vec[4].Normalize(); + originPlane[4] = (m.Get(4, 4) + m.Get(3, 4)) / l5; // Back plane vec[5].x = m.Get(4, 1) - m.Get(3, 1); vec[5].y = m.Get(4, 2) - m.Get(3, 2); vec[5].z = m.Get(4, 3) - m.Get(3, 3); - originPlane[5] = m.Get(4, 4) - m.Get(3, 4); + float l6 = vec[5].Length(); + vec[5].Normalize(); + originPlane[5] = (m.Get(4, 4) - m.Get(3, 4)) / l6; int result = 0; if (InPlane(vec[0], originPlane[0], center, radius)) - result |= INTERSECT_PLANE_LEFT; + result |= FRUSTUM_PLANE_LEFT; if (InPlane(vec[1], originPlane[1], center, radius)) - result |= INTERSECT_PLANE_RIGHT; + result |= FRUSTUM_PLANE_RIGHT; if (InPlane(vec[2], originPlane[2], center, radius)) - result |= INTERSECT_PLANE_TOP; + result |= FRUSTUM_PLANE_BOTTOM; if (InPlane(vec[3], originPlane[3], center, radius)) - result |= INTERSECT_PLANE_BOTTOM; + result |= FRUSTUM_PLANE_TOP; if (InPlane(vec[4], originPlane[4], center, radius)) - result |= INTERSECT_PLANE_FRONT; + result |= FRUSTUM_PLANE_FRONT; if (InPlane(vec[5], originPlane[5], center, radius)) - result |= INTERSECT_PLANE_BACK; + result |= FRUSTUM_PLANE_BACK; return result; } diff --git a/src/graphics/opengl/test/light_test.cpp b/src/graphics/opengl/test/light_test.cpp index 6ff3b1c..b19ba4b 100644 --- a/src/graphics/opengl/test/light_test.cpp +++ b/src/graphics/opengl/test/light_test.cpp @@ -51,7 +51,7 @@ void Render(Gfx::CGLDevice *device) device->SetRenderState(Gfx::RENDER_STATE_CULLING, false); // Double-sided drawing Math::Matrix persp; - Math::LoadProjectionMatrix(persp, Math::PI / 4.0f, (800.0f) / (600.0f), 0.1f, 100.0f); + Math::LoadProjectionMatrix(persp, Math::PI / 4.0f, (800.0f) / (600.0f), 0.1f, 50.0f); device->SetTransform(Gfx::TRANSFORM_PROJECTION, persp); @@ -121,6 +121,31 @@ void Render(Gfx::CGLDevice *device) Math::LoadTranslationMatrix(worldMat, Math::Vector(-40.0f, 2.0f, -40.0f)); device->SetTransform(Gfx::TRANSFORM_WORLD, worldMat); + int planes = device->ComputeSphereVisibility(Math::Vector(0.0f, 0.0f, 0.0f), 1.0f); + printf("Planes:"); + if (planes == 0) + printf(" (none)"); + + if (planes & Gfx::FRUSTUM_PLANE_LEFT) + printf(" LEFT"); + + if (planes & Gfx::FRUSTUM_PLANE_RIGHT) + printf(" RIGHT"); + + if (planes & Gfx::FRUSTUM_PLANE_BOTTOM) + printf(" BOTTOM"); + + if (planes & Gfx::FRUSTUM_PLANE_TOP) + printf(" TOP"); + + if (planes & Gfx::FRUSTUM_PLANE_FRONT) + printf(" FRONT"); + + if (planes & Gfx::FRUSTUM_PLANE_BACK) + printf(" BACK"); + + printf("\n"); + device->DrawPrimitive(Gfx::PRIMITIVE_TRIANGLE_STRIP, quad, 4); for (int i = 0; i < 6; ++i) diff --git a/src/graphics/opengl/test/texture_test.cpp b/src/graphics/opengl/test/texture_test.cpp index 534a5c0..d771927 100644 --- a/src/graphics/opengl/test/texture_test.cpp +++ b/src/graphics/opengl/test/texture_test.cpp @@ -13,7 +13,6 @@ void Init(Gfx::CGLDevice *device) device->SetShadeModel(Gfx::SHADE_SMOOTH); device->SetRenderState(Gfx::RENDER_STATE_DEPTH_TEST, false); - device->SetRenderState(Gfx::RENDER_STATE_TEXTURING, true); device->SetTextureEnabled(0, true); device->SetTextureEnabled(1, true); -- cgit v1.2.3-1-g7c22