#include "stdafx.h"
#include "Lines.h"

#include "Engine/Ray.h"
#include "Engine/Camera.h"
#include "Engine/SceneNode.h"
#include "Engine/Terrain.h"
#include "Engine/NaviMesh.h"
#include "Engine/NaviField.h"

cCircleLines::cCircleLines( const NiColorA& color0, const NiColorA& color1 )
{
	mPosCoords = NiNew NiPoint3[21];
	for( unsigned int i = 0; i < 21; ++i )
	{
		mPosCoords[i] = NiPoint3::ZERO;
	}

	mColors = NiNew NiColorA[21];
	for( unsigned int i = 0; i < 20; i += 2 )
	{
		mColors[i] = color0;
		mColors[i+1] = color1;
	}
	mColors[20] = color0;

	mFlags = NiAlloc( NiBool, 21 );
	for( unsigned int i = 0; i < 20; ++i )
	{
		mFlags[i] = 1;
	}
	mFlags[20] = 0;

	mLines = NiNew NiLines(
		21,
		mPosCoords,
		mColors,
		0,
		0,
		NiGeometryData::NBT_METHOD_NONE,
		mFlags );

	mMatProp = NiNew NiMaterialProperty;
	mMatProp->SetAmbientColor( NiColor::WHITE );
	mMatProp->SetDiffuseColor( NiColor::WHITE );
	mMatProp->SetSpecularColor( NiColor::WHITE );
	mMatProp->SetEmittance( NiColor::WHITE );

	mVertColorProp = NiNew NiVertexColorProperty;
	mVertColorProp->SetSourceMode( NiVertexColorProperty::SOURCE_EMISSIVE );
	mVertColorProp->SetLightingMode( NiVertexColorProperty::LIGHTING_E );

	mWireProp = NiNew NiWireframeProperty;
	mWireProp->SetWireframe( false );

	mLines->AttachProperty( mMatProp );
	mLines->AttachProperty( mVertColorProp );
	mLines->AttachProperty( mWireProp );
	mLines->UpdateProperties();
	mLines->Update( 0.0f );
}

void cCircleLines::Process( const NiPoint3& center, float radius, cTerrain* terrain )
{
	assert( terrain );

	float x, y;
	NiPoint3 org;
	NiPoint3 pos;

	for( unsigned int i = 0, ang = 0; ang < 360; ++i, ang += 18 )
	{
		x = NiCos( ang * NI_PI / 180.0f );
		y = NiSin( ang * NI_PI / 180.0f );

		pos.x = org.x = center.x + x * radius;
		pos.y = org.y = center.y + y * radius;
		org.z = 1000000.0f;
		pos.z = 0.0f;

		terrain->Pick( &pos, cRay(org, -NiPoint3::UNIT_Z) );

		mPosCoords[i].x = pos.x;
		mPosCoords[i].y = pos.y;
		mPosCoords[i].z = pos.z + 20.0f;
	}
	mPosCoords[20] = mPosCoords[0];

	NiGeometryData* geom = mLines->GetModelData();

	geom->Replace(
		21,
		mPosCoords,
		0,
		mColors,
		0,
		0,
		NiGeometryData::NBT_METHOD_NONE );

	geom->MarkAsChanged( NiGeometryData::VERTEX_MASK );
}

void cCircleLines::Process( const NiPoint3& center, float radius, cNaviMesh* naviMesh )
{
	assert( naviMesh );

	float x, y;
	NiPoint3 org;
	NiPoint3 pos;

	for( unsigned int i = 0, ang = 0; ang < 360; ++i, ang += 18 )
	{
		x = NiCos( ang * NI_PI / 180.0f );
		y = NiSin( ang * NI_PI / 180.0f );

		pos.x = org.x = center.x + x * radius;
		pos.y = org.y = center.y + y * radius;
		org.z = 1000000.0f;
		pos.z = 0.0f;

		naviMesh->Pick( &pos, cRay(org, -NiPoint3::UNIT_Z) );

		mPosCoords[i].x = pos.x;
		mPosCoords[i].y = pos.y;
		mPosCoords[i].z = pos.z + 100.0f;
	}
	mPosCoords[20] = mPosCoords[0];

	NiGeometryData* geom = mLines->GetModelData();

	geom->Replace(
		21,
		mPosCoords,
		0,
		mColors,
		0,
		0,
		NiGeometryData::NBT_METHOD_NONE );

	geom->MarkAsChanged( NiGeometryData::VERTEX_MASK );
}

void cCircleLines::Process( const NiPoint3& center, float radius, cNaviField* naviField )
{
	assert( naviField );

	float x, y;
	NiPoint3 org;
	NiPoint3 pos;

	for( unsigned int i = 0, ang = 0; ang < 360; ++i, ang += 18 )
	{
		x = NiCos( ang * NI_PI / 180.0f );
		y = NiSin( ang * NI_PI / 180.0f );

		pos.x = org.x = center.x + x * radius;
		pos.y = org.y = center.y + y * radius;
		org.z = 1000000.0f;
		pos.z = 0.0f;

		naviField->Pick( &pos, cRay(org, -NiPoint3::UNIT_Z) );

		mPosCoords[i].x = pos.x;
		mPosCoords[i].y = pos.y;
		mPosCoords[i].z = pos.z + 100.0f;
	}
	mPosCoords[20] = mPosCoords[0];

	NiGeometryData* geom = mLines->GetModelData();

	geom->Replace(
		21,
		mPosCoords,
		0,
		mColors,
		0,
		0,
		NiGeometryData::NBT_METHOD_NONE );

	geom->MarkAsChanged( NiGeometryData::VERTEX_MASK );
}

void cCircleLines::Process( cSceneNode* n, cCamera* cam )
{
	NiPoint3 right = cam->GetWorldRightVector();
	NiPoint3 up = cam->GetWorldUpVector();

	const NiPoint3& c = n->GetCenter();
	float r = n->GetRadius();
	float x, y;
	NiPoint3 dir;

	for( unsigned int i = 0, ang = 0; ang < 360; ++i, ang += 18 )
	{
		x = NiCos( ang * NI_PI / 180.0f );
		y = NiSin( ang * NI_PI / 180.0f );

		dir = right * x + up * y;
		mPosCoords[i] = c + dir * r;
	}

	mPosCoords[20] = mPosCoords[0];

	NiGeometryData* geom = mLines->GetModelData();

	geom->Replace(
		21,
		mPosCoords,
		0,
		mColors,
		0,
		0,
		NiGeometryData::NBT_METHOD_NONE );

	geom->MarkAsChanged( NiGeometryData::VERTEX_MASK );
}

void cCircleLines::Render()
{
	mLines->RenderImmediate( NiRenderer::GetRenderer() );
}
