ComputeSphereVisibility and fixes in CEngine TODOs
- view frustum culling with ComputeSphereVisibility - game should run faster now - resolved/removed most TODOs from CEngine - fixed OpenGL testsdev-ui
parent
728e7e405d
commit
688315ab76
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue