summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPiotr Dziwinski <piotrdz@gmail.com>2012-10-20 23:06:56 +0200
committerPiotr Dziwinski <piotrdz@gmail.com>2012-10-20 23:06:56 +0200
commit688315ab76145a32d0aebf826fbbb7fc9ce24443 (patch)
treea7d4e37fae1517a2b2eaf09a78219583caf97aa3
parent728e7e405dd56afb4da03fd63df378d5f984ed73 (diff)
downloadcolobot-688315ab76145a32d0aebf826fbbb7fc9ce24443.tar.gz
colobot-688315ab76145a32d0aebf826fbbb7fc9ce24443.tar.bz2
colobot-688315ab76145a32d0aebf826fbbb7fc9ce24443.zip
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
-rw-r--r--src/graphics/core/device.h29
-rw-r--r--src/graphics/engine/engine.cpp60
-rw-r--r--src/graphics/engine/engine.h6
-rw-r--r--src/graphics/engine/water.cpp6
-rw-r--r--src/graphics/opengl/gldevice.cpp80
-rw-r--r--src/graphics/opengl/test/light_test.cpp27
-rw-r--r--src/graphics/opengl/test/texture_test.cpp1
7 files changed, 122 insertions, 87 deletions
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 &center, 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<int>( 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<int>( 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 &center, 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 &center, 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);