/** SGX

The   sss    gggg x   x   
     s      g      x x    Engine
      sss   g  gg   x
         s  g   g  x x          Copyright 1995-2009.
     ssss    gggg x   x         Steven Goodwin. All Rights Reserved.
    
This version has been released under the GNU Public License v2.0.

Please see the license files for details.

File: sgx/src/domains/graphics/frustum/frustum.cpp

*/

#include "sgx/core/core.hpp"
#include "domains/graphics/graphics.hpp"

void 
CViewFrustum::recalculateFrustumPlanes(const sgxMatrix44 &m_ProjectViewTransform)
{
	m_FrustumPlanes[0] = sgxPlane(sgxVector3(m_ProjectViewTransform.right.w-m_ProjectViewTransform.right.x,  m_ProjectViewTransform.up.w-m_ProjectViewTransform.up.x,  m_ProjectViewTransform.at.w-m_ProjectViewTransform.at.x), m_ProjectViewTransform.pos.w-m_ProjectViewTransform.pos.x);	// right
	m_FrustumPlanes[1] = sgxPlane(sgxVector3(m_ProjectViewTransform.right.w+m_ProjectViewTransform.right.x,  m_ProjectViewTransform.up.w+m_ProjectViewTransform.up.x,  m_ProjectViewTransform.at.w+m_ProjectViewTransform.at.x), m_ProjectViewTransform.pos.w+m_ProjectViewTransform.pos.x);	// left
	m_FrustumPlanes[2] = sgxPlane(sgxVector3(m_ProjectViewTransform.right.w+m_ProjectViewTransform.right.y,  m_ProjectViewTransform.up.w+m_ProjectViewTransform.up.y,  m_ProjectViewTransform.at.w+m_ProjectViewTransform.at.y), m_ProjectViewTransform.pos.w+m_ProjectViewTransform.pos.y);	// bottom
	m_FrustumPlanes[3] = sgxPlane(sgxVector3(m_ProjectViewTransform.right.w-m_ProjectViewTransform.right.y,  m_ProjectViewTransform.up.w-m_ProjectViewTransform.up.y,  m_ProjectViewTransform.at.w-m_ProjectViewTransform.at.y), m_ProjectViewTransform.pos.w-m_ProjectViewTransform.pos.y);	// top
	m_FrustumPlanes[4] = sgxPlane(sgxVector3(m_ProjectViewTransform.right.w-m_ProjectViewTransform.right.z,  m_ProjectViewTransform.up.w-m_ProjectViewTransform.up.z,  m_ProjectViewTransform.at.w-m_ProjectViewTransform.at.z), m_ProjectViewTransform.pos.w-m_ProjectViewTransform.pos.z);	// front
	m_FrustumPlanes[5] = sgxPlane(sgxVector3(m_ProjectViewTransform.right.w+m_ProjectViewTransform.right.z,  m_ProjectViewTransform.up.w+m_ProjectViewTransform.up.z,  m_ProjectViewTransform.at.w+m_ProjectViewTransform.at.z), m_ProjectViewTransform.pos.w+m_ProjectViewTransform.pos.z);	// back
}

tBOOL	
CViewFrustum::isInside(const sgxVector3 &pos) const
{
	return isInside(pos, 0);
}

tBOOL	
CViewFrustum::isInside(const sgxMatrix43 &transform) const
{
	return isInside(transform.pos);
}

tBOOL	
CViewFrustum::isInside(const sgxPrimitivePolygon &poly) const
{
	sgxVector<sgxPolyVtx>::const_iterator cit=poly.vtx.begin();

	for(;cit!=poly.vtx.end();++cit) {
		if (isInside((*cit).vect)) {
			return TRUE;
		}
	}
	
	return FALSE;
}

tBOOL	
CViewFrustum::isInside(const sgxPrimitivePolygon &poly, const sgxMatrix43 &transform) const
{
	sgxVector<sgxPolyVtx>::const_iterator cit=poly.vtx.begin();

	for(;cit!=poly.vtx.end();++cit) {
		sgxVector3 v = (*cit).vect;

		v.transform(transform);

		if (isInside(v)) {
			return TRUE;
		}
	}
	
	return FALSE;
}


tBOOL	
CViewFrustum::isAllInside(const sgxPrimitivePolygon &poly, const sgxMatrix43 &transform) const
{
	sgxVector<sgxPolyVtx>::const_iterator cit=poly.vtx.begin();

	for(;cit!=poly.vtx.end();++cit) {
		sgxVector3 v = (*cit).vect;

		v.transform(transform);

		if (!isInside(v)) {
			return FALSE;
		}
	}
	
	return TRUE;
}

