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


		#include "gpu/gpu_geometry.h"
		#include "gpu/gpu_renderer.h"
		#include "core/geometry.h"
		#include "core/geometry_to_triangle_list.h"
		#include "core/triangle_list.h"
		#include "log/log.h"

		using namespace GS::GPU;


//------------------------------------------------------------------------------
bool				Geometry::AllocateVBO(uint count)
{
	if	(!vbo.Allocate(count))
		return false;

	for	(uint n = 0; n < count; ++n)
		vbo[n] = renderer.NewVBO();

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

//------------------------------------------------------------------------------
bool				Geometry::SetMaterial(uint index, GS::Render::Material *m)
{
	if	(index >= material_table.GetCount())
		return false;

	// Update all display lists using this material index.
	for (uint n = 0; n < display_list.GetCount(); ++n)
		if	(DisplayList *dlist = display_list[n])
			if	(dlist->material == material_table[index])
				dlist->material = (GPU::Material *)m;

	// Update the material table.
	material_table[index] = m;

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

//------------------------------------------------------------------------------
bool				Geometry::ShouldReloadOnDependencyChange(const char *n) const
{
	for (uint i = 0; i < material_table.GetCount(); ++i)
		if	(material_table[i] && (material_table[i]->name == n))
				return true;

	return name == n;
}
//------------------------------------------------------------------------------

//------------------------------------------------------------------------------
bool				Geometry::Create(GS::Render::ResourceFactory &rf, const GS::Core::Geometry &g)
{
	__LOG_H__ << "Setup geometry '" << g.name << "'.\n";
	name = g.name;

	using namespace Core;

	// Setup materials.
	if	(material_table.Allocate(g.material_table.GetCount()))
		for (uint n = 0; n < g.material_table.GetCount(); ++n)
			material_table[n] = rf.LoadMaterial(g.material_table[n].name, !g.material_table[n].use_cache);

	// Build geometry triangle list.
	AutoList <Trilist *> tlist;
	if	(!GeometryToTriangleList::Convert(g, tlist))
		return false;

	// Setup geometry display lists.
	if	(display_list.Allocate(tlist.GetCount()))
	{
		uint n = 0;
		ListForeachPtr(Trilist *, t, tlist)
		{
			display_list[n] = renderer.NewDisplayList();
			display_list[n]->Create(t, material_table[t->mat]);
			++n;
		}
	}
	flag = g.flag;

	// Skinning.
	bone_bind_matrix.Clone(g.bone_bind_matrix);
	g.ComputeBoneBoundingVolumes(bone_minmax);

	// Load proxies.
	if	(!g.lod_proxy.IsEmpty())
		lod_proxy = rf.LoadGeometry(g.lod_proxy);
	lod_distance = g.lod_distance;

	if	(!g.shadow_proxy.IsEmpty())
		shadow_proxy = rf.LoadGeometry(g.shadow_proxy);

	minmax = g.ComputeMinMax();
//	hotspot.Set(0, 0, 0);
	hotspot = (minmax.mn + minmax.mx) * 0.5f;

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