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
dev-ui
Piotr Dziwinski 2012-10-20 23:06:56 +02:00
parent 728e7e405d
commit 688315ab76
7 changed files with 122 additions and 87 deletions

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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;
}

View File

@ -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)

View File

@ -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);