// lib_graph::Materialと, OpenGLのカレントマテリアルの入出力機能

#pragma once

#include "../graph/Color.h"
#include "../graph/Material.h"

#include <sstream>



namespace lib_gl
{


//! Phongのマテリアル. OpenGL版
class MaterialSetter
{
public:
	//! 指定した面にマテリアルを適用する
	static void SetGL( const lib_graph::Material& i_material , GLenum face_type = GL_FRONT_AND_BACK , bool set_diffuse_to_color = true );

	//! OpenGLのカレントマテリアルを取得.
	//! GL_FRONT_AND_BACKは取得できないので注意
	static void GetGL( lib_graph::Material& i_material , GLenum face_type = GL_FRONT );


	//! 指定した両面マテリアルを適用する
	static void SetGL( const lib_graph::DoublesideMaterial& i_material );

	//! OpenGLのカレントマテリアルを両面マテリアルオブジェクトに取得.
	static void GetGL( lib_graph::DoublesideMaterial& i_material );
};



// implements

//! 指定した面にマテリアルを適用する
//! @param face_type            - マテリアルを適用する面
//! @param set_diffuse_to_color - trueなら、diffuseをglColorにセットする
inline void MaterialSetter::SetGL( const lib_graph::Material& i_material , GLenum face_type , bool set_diffuse_to_color )
{
	glMaterialfv( face_type , GL_AMBIENT   , i_material.m_Ambient.v()  );
	glMaterialfv( face_type , GL_DIFFUSE   , i_material.m_Diffuse.v()  );
	glMaterialfv( face_type , GL_SPECULAR  , i_material.m_Specular.v() );
	glMaterialfv( face_type , GL_EMISSION  , i_material.m_Emission.v() );

	static const float MAX_SH = 128.0f;
	float sh = i_material.m_Shininess;
	if (sh > MAX_SH)
	{
		std::ostringstream ss;
		ss << "MaterialSetter::SetGL : modified shininess " << sh << " to " << MAX_SH << std::endl;
		OutputDebugStringA(ss.str().c_str());

		sh = MAX_SH;
	}

	glMaterialfv(face_type, GL_SHININESS, &sh);
	
	if( set_diffuse_to_color )
		glColor4fv( i_material.m_Diffuse.v() );
}

//! OpenGLのカレントマテリアルを取得.
//! GL_FRONT_AND_BACKは取得できないので注意
inline void MaterialSetter::GetGL( lib_graph::Material& i_material , GLenum face_type )
{
	glGetMaterialfv( face_type , GL_AMBIENT   , i_material.m_Ambient.v()  );
	glGetMaterialfv( face_type , GL_DIFFUSE   , i_material.m_Diffuse.v()  );
	glGetMaterialfv( face_type , GL_SPECULAR  , i_material.m_Specular.v() );
	glGetMaterialfv( face_type , GL_EMISSION  , i_material.m_Emission.v() );
	glGetMaterialfv( face_type , GL_SHININESS , &i_material.m_Shininess   );
}

//! 指定した両面マテリアルを適用する
inline void MaterialSetter::SetGL( const lib_graph::DoublesideMaterial& i_material )
{
	SetGL( i_material.m_FrontMaterial , GL_FRONT , false );
	SetGL( i_material.m_BackMaterial  , GL_BACK  , false );
}

//! OpenGLのカレントマテリアルを両面マテリアルオブジェクトに取得.
inline void MaterialSetter::GetGL( lib_graph::DoublesideMaterial& i_material )
{
	GetGL( i_material.m_FrontMaterial , GL_FRONT );
	GetGL( i_material.m_BackMaterial  , GL_BACK  );
}


}
