From: <axl...@us...> - 2009-07-06 16:18:19
|
Revision: 413 http://hgengine.svn.sourceforge.net/hgengine/?rev=413&view=rev Author: axlecrusher Date: 2009-07-06 16:18:18 +0000 (Mon, 06 Jul 2009) Log Message: ----------- simple bounding box frustum culling is working Modified Paths: -------------- Mercury2/src/BoundingBox.cpp Mercury2/src/HGMDLModel.cpp Mercury2/src/HGMDLModel.h Mercury2/src/MercuryAsset.cpp Mercury2/src/MercuryAsset.h Mercury2/src/MercuryNode.cpp Mercury2/src/MercuryPlane.cpp Modified: Mercury2/src/BoundingBox.cpp =================================================================== --- Mercury2/src/BoundingBox.cpp 2009-07-06 16:14:59 UTC (rev 412) +++ Mercury2/src/BoundingBox.cpp 2009-07-06 16:18:18 UTC (rev 413) @@ -56,37 +56,77 @@ void BoundingBox::ComputeNormals() { - //normals are probably just the cardinal axises -/* MercuryVertex t(m_center, 0); + //these need to be the normals of each face + /* + MercuryVertex t(m_center, 0); t.SetX( t.GetX() + m_extend.GetX() ); - m_normals[0] = t;//.Normalize(); + m_normals[0] = (m_center - t).Normalize(); t = m_center; t.SetY( t.GetY() + m_extend.GetY() ); - m_normals[1] = t;//.Normalize(); + m_normals[1] = (m_center - t).Normalize(); t = m_center; t.SetZ( t.GetZ() + m_extend.GetZ() ); - m_normals[2] = t;//.Normalize(); + m_normals[2] = (m_center - t).Normalize(); + m_normals[0].Print(); */ } void BoundingBox::Transform( const MercuryMatrix& m ) { + //the frustum planes are defined in world space so + //these values need to be transformed into world space BoundingBox bb; - bb.m_extend = m_extend; - MercuryMatrix mm = m * FRUSTUM->GetMatrix(); - bb.m_center = mm * MercuryVertex(m_center, 1); - bb.m_normals[0] = (mm * MercuryVector(1.0f,0,0,0)).Normalize(); - bb.m_normals[1] = (mm * MercuryVector(0,1.0f,0,0)).Normalize(); - bb.m_normals[2] = (mm * MercuryVector(0,0,1.0f,0)).Normalize(); -// bb.Render(); + bb.m_extend = m * m_extend; //Rotate and scale + bb.m_center = m * MercuryVertex(m_center, 1); + + //transform the box axises into world axises + bb.m_normals[0] = (m * MercuryVector(1,0,0)).Normalize(); + bb.m_normals[1] = (m * MercuryVector(0,1,0)).Normalize(); + bb.m_normals[2] = (m * MercuryVector(0,0,1)).Normalize(); + *this = bb; } bool BoundingBox::Clip( const MercuryPlane& p ) { - MercuryVertex dp = p.GetNormal().DotProduct3(m_normals[0], m_normals[1], m_normals[2]); + //do a quick spherical test using the signed distance + float d = p.GetNormal().DotProduct( m_center - p.GetCenter() ); + if (d < -m_extend.Length()) return true; + return false; + + ///XXX everything below is broken + + MercuryVector dp; //plain normal in box space +// dp = p.GetNormal().DotProduct3(m_normals[0],m_normals[2],m_normals[3]); + dp[0] = m_normals[0].DotProduct( p.GetNormal() ); + dp[1] = m_normals[1].DotProduct( p.GetNormal() ); + dp[2] = m_normals[2].DotProduct( p.GetNormal() ); + dp.NormalizeSelf(); +// dp = p.GetNormal(); + + MercuryVertex P; //max + if (dp[0] >= 0) P[0] = m_center.GetX() + m_extend.GetX(); + if (dp[1] >= 0) P[1] = m_center.GetY() + m_extend.GetY(); + if (dp[2] >= 0) P[2] = m_center.GetZ() + m_extend.GetZ(); + + MercuryVertex N; //min + if (dp[0] >= 0) N[0] = m_center.GetX() - m_extend.GetX(); + if (dp[1] >= 0) N[1] = m_center.GetY() - m_extend.GetY(); + if (dp[2] >= 0) N[2] = m_center.GetZ() - m_extend.GetZ(); + + float x = dp.DotProduct( P ); + float y = dp.DotProduct( N ); +// printf("p %f n %f\n", x, y); + if ( x < 0) + return true; //max value outside + if ( y < 0) //is negative value outside + return false; //intersect + + return false; +/* + db * m_extend; float x = ABS( m_extend.GetX() * dp[0] ); x += ABS( m_extend.GetY() * dp[1] ); x += ABS( m_extend.GetZ() * dp[2] ); @@ -96,17 +136,22 @@ return false; return BEHIND_PLANE(d); //if we don't intersect, just see what side we are on + */ } bool BoundingBox::Clip( const Frustum& f ) { - bool inView = true; - for (uint8_t i = 0; (i < 6) && inView; ++i) + bool clipped = false; + for (uint8_t i = 0; (i < 6) && !clipped; ++i) { - inView = Clip( f.GetPlane(i) )?false:inView; + bool t = Clip( f.GetPlane(i) ); +// printf("p%d %d\n", i, t); + clipped = t; } +// printf("******\n"); +// return false; - return !inView; + return clipped; } //bool BoundingBox::FrustumCull() const @@ -166,8 +211,10 @@ bool BoundingBox::DoFrustumTest( const MercuryMatrix& m ) { BoundingBox bb(*this); +// bb.Render(); bb.Transform( m ); - return false; +// bb.Render(); + return bb.Clip( *FRUSTUM ); } void BoundingBox::DoOcclusionTest( OcclusionResult& result ) @@ -218,7 +265,7 @@ const float* center = GetCenter(); const float* extend = GetExtend(); -// glPushMatrix(); + glPushMatrix(); // glLoadIdentity(); glPushAttrib( GL_CURRENT_BIT ); glBegin(GL_LINES); @@ -258,34 +305,45 @@ glEnd(); - //center glPointSize(4); glBegin(GL_POINTS); + //center glVertex3f(center[0], center[1], center[2]); + //max point + glColor3f(1,1,0); + glVertex3f(center[0]+extend[0], center[1]+extend[1], center[2]+extend[2]); + //min point +// glColor3f(1,0,0); + glVertex3f(center[0]-extend[0], center[1]-extend[1], center[2]-extend[2]); glEnd(); + //normals MercuryVertex c; glBegin(GL_LINES); + glColor3f(1.0f,0,0); glVertex3f(center[0], center[1], center[2]); c = center; c += m_normals[0]; glVertex3f(c.GetX(), c.GetY(), c.GetZ()); + glColor3f(0,1.0f,0); glVertex3f(center[0], center[1], center[2]); c = center; c += m_normals[1]; glVertex3f(c.GetX(), c.GetY(), c.GetZ()); + glColor3f(0,0,1.0f); glVertex3f(center[0], center[1], center[2]); c = center; c += m_normals[2]; glVertex3f(c.GetX(), c.GetY(), c.GetZ()); + glEnd(); glPopAttrib( ); -// glPopMatrix(); + glPopMatrix(); } void BoundingBox::PopulateVertices() Modified: Mercury2/src/HGMDLModel.cpp =================================================================== --- Mercury2/src/HGMDLModel.cpp 2009-07-06 16:14:59 UTC (rev 412) +++ Mercury2/src/HGMDLModel.cpp 2009-07-06 16:18:18 UTC (rev 413) @@ -58,6 +58,13 @@ } } +void HGMDLModel::DoCullingTests(MercuryNode* n, const MercuryMatrix& matrix) +{ + if ( GetLoadState() != LOADING ) + for(uint16_t i = 0; i < m_meshes.size(); ++i) + m_meshes[i]->DoCullingTests(n, matrix); +} + void HGMDLModel::PreRender(const MercuryNode* node) { if ( GetLoadState() != LOADING ) Modified: Mercury2/src/HGMDLModel.h =================================================================== --- Mercury2/src/HGMDLModel.h 2009-07-06 16:14:59 UTC (rev 412) +++ Mercury2/src/HGMDLModel.h 2009-07-06 16:18:18 UTC (rev 413) @@ -19,6 +19,7 @@ static HGMDLModel* Generate(); + virtual void DoCullingTests(MercuryNode* n, const MercuryMatrix& matrix); virtual void PreRender(const MercuryNode* node); virtual void Render(const MercuryNode* node); Modified: Mercury2/src/MercuryAsset.cpp =================================================================== --- Mercury2/src/MercuryAsset.cpp 2009-07-06 16:14:59 UTC (rev 412) +++ Mercury2/src/MercuryAsset.cpp 2009-07-06 16:18:18 UTC (rev 413) @@ -37,8 +37,19 @@ SetLoadState( LOADED ); } +void MercuryAsset::DoCullingTests(MercuryNode* n, const MercuryMatrix& matrix) +{ + if ( m_boundingVolume ) + { + n->SetCulled( m_boundingVolume->DoFrustumTest(matrix) ); + if ( !n->IsCulled() ) + m_boundingVolume->DoOcclusionTest( n->GetOcclusionResult() ); + } +} + void MercuryAsset::PreRender(const MercuryNode* node) { + /* MercuryNode* n = const_cast<MercuryNode*>(node); if ( m_boundingVolume ) { @@ -46,6 +57,7 @@ if ( !n->IsCulled() ) m_boundingVolume->DoOcclusionTest( n->GetOcclusionResult() ); } + */ } void MercuryAsset::DrawAxes() Modified: Mercury2/src/MercuryAsset.h =================================================================== --- Mercury2/src/MercuryAsset.h 2009-07-06 16:14:59 UTC (rev 412) +++ Mercury2/src/MercuryAsset.h 2009-07-06 16:18:18 UTC (rev 413) @@ -51,6 +51,7 @@ inline BoundingVolume* GetBoundingVolume() const { return m_boundingVolume; } inline const MString& Path() const { return m_path; } + virtual void DoCullingTests(MercuryNode* n, const MercuryMatrix& matrix); void DrawAxes(); protected: void SetLoadState(LoadState ls); //thread safe Modified: Mercury2/src/MercuryNode.cpp =================================================================== --- Mercury2/src/MercuryNode.cpp 2009-07-06 16:14:59 UTC (rev 412) +++ Mercury2/src/MercuryNode.cpp 2009-07-06 16:18:18 UTC (rev 413) @@ -224,7 +224,10 @@ { list< MercuryAsset* >::iterator i; for (i = m_prerender.begin(); i != m_prerender.end(); ++i ) + { + (*i)->DoCullingTests( this, matrix ); (*i)->PreRender(this); + } } void MercuryNode::Render(const MercuryMatrix& matrix) Modified: Mercury2/src/MercuryPlane.cpp =================================================================== --- Mercury2/src/MercuryPlane.cpp 2009-07-06 16:14:59 UTC (rev 412) +++ Mercury2/src/MercuryPlane.cpp 2009-07-06 16:18:18 UTC (rev 413) @@ -2,14 +2,10 @@ #include <stdio.h> #include <MercuryMath.h> -#define SIGNED_DIST(x) m_normal.DotProduct(x) - -// origional algorithim was -x<0 -#define BEHIND_PLANE(x) x>=0 - bool MercuryPlane::IsBehindPlane(const MercuryVertex& point) const { - return BEHIND_PLANE( SIGNED_DIST( point+m_center ) ); + //signed distance between the plane and the point + return m_normal.DotProduct( point - m_center ) < 0; } /**************************************************************************** This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |