www.pudn.com > Gimcrack-v0.0051-Source.zip > frustum.cpp


#include  
#include  
#include "math/math.h" 
#include "math/matrix.h" 
#include "frustum.h" 
#include "math/aabb.h" 
 
////////////////////////////////////////////////////////////////////////////////// 
 
static GcFrustum *frust = NULL; 
 
GcFrustum *ActiveFrustum() 
{ 
    return frust; 
} 
 
////////////////////////////////////////////////////////////////////////////////// 
 
GcFrustum::GcFrustum() 
{ 
	frust = this; 
} 
 
////////////////////////////////////////////////////////////////////////////////// 
 
GcFrustum::~GcFrustum() 
{ 
	frust = NULL; 
} 
 
////////////////////////////////////////////////////////////////////////////////// 
 
void GcFrustum::Extract() 
{ 
	GcMatrix4 projection; 
	GcMatrix4 model; 
	GcMatrix4 clip; 
	GcVector4 temp[6]; 
 
 
	// Get the projection and modelview matrix from OpenGL 
	glGetFloatv(GL_PROJECTION_MATRIX, projection); 
	glGetFloatv(GL_MODELVIEW_MATRIX, model); 
 
	// Combine the two matrices 
	clip = projection * model; 
 
	// Extract the right plane 
	temp[0].x = clip[ 3] - clip[ 0]; 
	temp[0].y = clip[ 7] - clip[ 4]; 
	temp[0].z = clip[11] - clip[ 8]; 
	temp[0].w = clip[15] - clip[12]; 
 
	// Normalize the vector 
	temp[0].NormalizePlane(); 
 
	// Extract the left plane 
	temp[1].x = clip[ 3] + clip[ 0]; 
	temp[1].y = clip[ 7] + clip[ 4]; 
	temp[1].z = clip[11] + clip[ 8]; 
	temp[1].w = clip[15] + clip[12]; 
 
	// Normalize the vector 
	temp[1].NormalizePlane(); 
 
	// Extract the bottom plane 
	temp[2].x = clip[ 3] + clip[ 1]; 
	temp[2].y = clip[ 7] + clip[ 5]; 
	temp[2].z = clip[11] + clip[ 9]; 
	temp[2].w = clip[15] + clip[13]; 
 
	// Normalize the vector 
	temp[2].NormalizePlane(); 
 
	// Extract the top plane 
	temp[3].x = clip[ 3] - clip[ 1]; 
	temp[3].y = clip[ 7] - clip[ 5]; 
	temp[3].z = clip[11] - clip[ 9]; 
	temp[3].w = clip[15] - clip[13]; 
 
	// Normalize the vector 
	temp[3].NormalizePlane(); 
 
	// Extract the far plane 
	temp[4].x = clip[ 3] - clip[ 2]; 
	temp[4].y = clip[ 7] - clip[ 6]; 
	temp[4].z = clip[11] - clip[10]; 
	temp[4].w = clip[15] - clip[14]; 
 
	// Normalize the vector 
	temp[4].NormalizePlane(); 
 
	// Extract the near plane 
	temp[5].x = clip[ 3] + clip[ 2]; 
	temp[5].y = clip[ 7] + clip[ 6]; 
	temp[5].z = clip[11] + clip[10]; 
	temp[5].w = clip[15] + clip[14]; 
 
	// Normalize the vector 
	temp[5].NormalizePlane(); 
 
	for( int i = 0; i < 6; ++i ) 
	{ 
		m_frustum[i].SetPlane(GcVector3(temp[i].x, temp[i].y, temp[i].z), temp[i].w); 
	} 
} 
 
////////////////////////////////////////////////////////////////////////////////// 
 
/*bool GcFrustum::BoxInFrustum(float x, float y, float z, float size, float height) 
{ 
	// Check to see if a box is in the frustum  
 
	// Loop through all planes looking to see if the point is infront of it 
	for(int i = 0; i < 6; i++ ) 
	{ 
		// Check to see if any of the box's points is infront of the plane 
		// If it is continue to the next plane, if none are then the box outside the frustum 
		if(frustum[i].x * x + frustum[i].y * y +  
		   frustum[i].z * z + frustum[i].w > 0 ) { 
			continue; 
		} 
		if(frustum[i].x * (x + size) + frustum[i].y * y +  
		   frustum[i].z * z	+ frustum[i].w > 0 ) { 
			continue; 
		} 
		if(frustum[i].x * x + frustum[i].y * (y + height) +  
		   frustum[i].z * z + frustum[i].w > 0 ) { 
			continue; 
		} 
		if(frustum[i].x * (x + size) + frustum[i].y * (y + height) +  
		   frustum[i].z * z + frustum[i].w > 0 ) { 
			continue; 
		} 
		if(frustum[i].x * x + frustum[i].y * y +  
		   frustum[i].z * (z + size) + frustum[i].w > 0 ) { 
			continue; 
		} 
		if(frustum[i].x * (x + size) + frustum[i].y * y +  
		   frustum[i].z * (z + size) + frustum[i].w > 0 ) { 
			continue; 
		} 
		if(frustum[i].x * x + frustum[i].y * (y +height) +  
		   frustum[i].z * (z + size) + frustum[i].w > 0 ) { 
			continue; 
		} 
		if(frustum[i].x * (x + size) + frustum[i].y * (y + height) +  
		   frustum[i].z * (z + size) + frustum[i].w > 0 ) { 
			continue; 
		} 
		return false; 
	} 
	return true; 
} 
*/ 
////////////////////////////////////////////////////////////////////////////////// 
 
bool GcFrustum::Contains(GcAABB & aabb) 
{ 
	for(int i = 0; i < 6; ++i) 
	{ 
		if(m_frustum[i].Distance(aabb.Point(0)) > 0) continue; 
		if(m_frustum[i].Distance(aabb.Point(1)) > 0) continue; 
		if(m_frustum[i].Distance(aabb.Point(2)) > 0) continue; 
		if(m_frustum[i].Distance(aabb.Point(3)) > 0) continue; 
		if(m_frustum[i].Distance(aabb.Point(4)) > 0) continue; 
		if(m_frustum[i].Distance(aabb.Point(5)) > 0) continue; 
		if(m_frustum[i].Distance(aabb.Point(6)) > 0) continue; 
		if(m_frustum[i].Distance(aabb.Point(7)) > 0) continue; 
 
		// Ok, give up. The point isn't in the frustum 
		return false; 
	} 
 
	return true; 
}