
//**************************************************************************/
// Copyright (c) 2008 Autodesk, Inc.
// All rights reserved.
//
// Use of this software is subject to the terms of the Autodesk license
// agreement provided at the time of installation or download, or which
// otherwise accompanies this software in either electronic or hard copy form.
//
//**************************************************************************/
// DESCRIPTION:
// CREATED: October 2008
//**************************************************************************/

#include "FixedFunctionMaterial.h"

/// Plug-in Macro
MB_PLUGIN( "FixedFunctionMaterial", "Fixed function material", "Autodesk", "http://www.mudbox3d.com", 0 );

/// More plug-in Macro
IMPLEMENT_CLASS( FixedFunctionMaterial, Material, "Fixed Function Material" );

/// Constructor
FixedFunctionMaterial::FixedFunctionMaterial( void ) : 
				m_sTexture(this, "Texture"),
				m_cDiffuse(this, "Diffuse"),
				m_cSpecular(this, "Specular"),
				m_cEmissive(this, "Emmissive"),
				m_fShiny(this, "Shininess"),
				m_iDiffuseTexture(-1)
{
	SetName( "Benchmark Material" );

	/// Creates the texture container
	m_pTexturePool = CreateInstance<TexturePool>();

	m_cSpecular.SetValue(Color(0,0,0,0));
	m_cEmissive.SetValue(Color(0,0,0,0));
	m_cDiffuse.SetValue(Color(.2f, .02f, .8f));

	// Sets texture to diffuse color.
	m_pDiffuseTexture[0] = (GLubyte) (m_cDiffuse.Value().r * 255);
	m_pDiffuseTexture[1] = (GLubyte) (m_cDiffuse.Value().g * 255);
	m_pDiffuseTexture[2] = (GLubyte) (m_cDiffuse.Value().b * 255);

	// Create OpenGL texture ID.
	glGenTextures(1, &m_iDiffuseTexture);

	m_fShiny.SetMax(128);
	m_fShiny.SetMin(0);
	m_fShiny = 100;
};

FixedFunctionMaterial::~FixedFunctionMaterial( void )
{
	// Clean up
	delete m_pTexturePool;
    glDeleteTextures(1, &m_iDiffuseTexture);
};

bool FixedFunctionMaterial::Activate( const Mesh *pMesh, const AxisAlignedBoundingBox &cUVArea, const Color &cColor )
{
	// Render settings
	glEnable( GL_LIGHTING );
	glEnable( GL_CULL_FACE );

	glMaterialfv( GL_FRONT, GL_EMISSION, m_cEmissive.Value() );
	glMaterialfv( GL_FRONT, GL_SPECULAR, m_cSpecular.Value() );
	glMateriali(GL_FRONT, GL_SHININESS, (int) m_fShiny);
	glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);

	// Get the correct texture for this tile.
	class Texture *pT = m_pTexturePool->Tile( cUVArea );
	if ( pT )
	{
		glEnable( GL_TEXTURE_2D );
		pT->Activate();
	}
	else
		glDisable( GL_TEXTURE_2D );

	glEnable(GL_TEXTURE_2D);
	glBindTexture(GL_TEXTURE_2D, m_iDiffuseTexture);
	glTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
	glTexParameterf( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );

	// Apply the texture
	glTexImage2D(GL_TEXTURE_2D, 0,
		GL_RGB8, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, &m_pDiffuseTexture);

	return true;
};

void FixedFunctionMaterial::Deactivate( void )
{
	glDisable(GL_TEXTURE_2D);
};

void FixedFunctionMaterial::OnNodeEvent( const Attribute &cAttribute, NodeEventType cType )
{
	// UI events.
	bool bRedraw = false;
	if ( cType == etValueChanged && cAttribute == m_sTexture )
	{
		m_pTexturePool->SetFileName( (const char*) m_sTexture.Value().toAscii() );
		bRedraw = true;
	};

	if (cAttribute == m_cDiffuse || cAttribute == m_cEmissive ||
		cAttribute == m_cSpecular || cAttribute == m_fShiny)
		bRedraw = true;

	if (cAttribute == m_cDiffuse)
	{
		m_pDiffuseTexture[0] = (GLubyte) (m_cDiffuse.Value().r * 255);
		m_pDiffuseTexture[1] = (GLubyte) (m_cDiffuse.Value().g * 255);
		m_pDiffuseTexture[2] = (GLubyte) (m_cDiffuse.Value().b * 255);
	}

	Material::OnNodeEvent( cAttribute, cType );

	if (bRedraw)
		Kernel()->Redraw();
};
