/* -----------------------------------------------------------------------------
	GSFramework
	Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
----------------------------------------------------------------------------- */


		#include "core/geometry.h"
		#include "log/log.h"

		using namespace GS;
		using namespace GS::Core;


//------------------------------------------------------------------------------
bool				Geometry::ComputePolygonNormal(bool force)
{
	if	(!pol.GetCount() || !vtx.GetCount())
		return false;

	if	(!force && (pol_normal.GetCount() == pol.GetCount()))
		return true;

	if	(!pol_normal.Allocate(pol.GetCount()))
		__ERR__(__LOG_E__ << "Geometry::ComputePolygonNormal() failed to allocate buffer.\n", false)

	for	(uint c = 0; c < pol.GetCount(); ++c)
		if (pol[c].vtx_count > 2)
		{
			Vector4	va = vtx[pol[c].binding[2]] - vtx[pol[c].binding[0]],
					vb = vtx[pol[c].binding[1]] - vtx[pol[c].binding[0]];
			pol_normal[c] = vb.Cross(va).Normalized();
		}
		else
			pol_normal[c].Set();

	return true;
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
bool				Geometry::ComputeVertexNormal(Array <Vector4> &buffer, float msa)
{
	if	(!pol.GetCount() || !vtx.GetCount())
		return false;

	if	(!ComputePolygonNormal())
		return false;

	Array <VertexToPolygon> vtx_to_pol;
	ComputeVertexToPolygon(vtx_to_pol);

	// Allocate full blown edge normal array.
	__LOG__ << "Compute vertex normal for " << name << ".\n";

	if	(!binding.GetCount())
		__ERR__(__LOG_E__ << "The total binding count is wrong. Check that the importer did properly update this flag.\n", false)
	if	(!vtx_normal.Allocate(binding.GetCount()))
		__ERR__(__LOG_E__ << "Failed to allocate vertex normal buffer.\n", false)

	for	(uint cp = 0, ttp = 0; cp < pol.GetCount(); cp++)
		for	(uint cv = 0; cv < pol[cp].vtx_count; cv++)
		{
			uint gv = pol[cp].binding[cv];

			Vector4	normal(0, 0, 0);
			for	(uint cg = 0; cg < vtx_to_pol[gv].pol_count; cg++)
				if	(pol_normal[cp].Dot(pol_normal[vtx_to_pol[gv].pol_index[cg]]) > msa)	// MSA test.
					normal += pol_normal[vtx_to_pol[gv].pol_index[cg]];

			vtx_normal[ttp++] = normal.Normalized();
		}

	return true;
}
bool				Geometry::ComputeVertexNormal(float msa, bool force)
{
	if	(!force && (vtx_normal.GetCount() == binding.GetCount()))
		return true;
	return ComputeVertexNormal(vtx_normal, msa);
}
//------------------------------------------------------------------------------
