#include "Mix/Private/Scene/Standard/Common/DefaultMaterial.h"

#include "Mix/IO/IReader.h"
#include "Mix/Graphics/IDevice.h"
#include "Mix/Graphics/IVertexLayout.h"
#include "Mix/Graphics/IVertexShader.h"
#include "Mix/Graphics/IPixelShader.h"
#include "Mix/Graphics/ITexture.h"

#include "Mix/Private/Scene/Standard/Common/EffectPackage.h"

namespace Mix{ namespace Scene{ namespace Standard{ namespace Common{

const wchar_t* DefaultMaterial::FAILED_CREATE = L"デフォルトマテリアルの作成に失敗";
const wchar_t* DefaultMaterial::FAILED_CLONE = L"デフォルトマテリアルの複製に失敗";

const Mix::Vector2 DefaultMaterial::WAVE_VEC_TABLE[4] = 
{
	Mix::Vector2( -1.0f,  0.0f ),
	Mix::Vector2(  1.0f,  0.0f ),
	Mix::Vector2(  0.0f, -1.0f ),
	Mix::Vector2(  0.0f,  1.0f ),
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::Standard::Common::DefaultMaterial
////////////////////////////////////////////////////////////////////////////////////////////////////

DefaultMaterial::DefaultMaterial( void ) :
m_Name( L"" ),
m_ShaderType( Mix::Scene::IDefaultMaterial::SHADER_NORMAL ),
m_BlendType( Mix::Graphics::BLEND_COPY ),
m_CullType( Mix::Graphics::CULL_BACK ),
m_bBothFacesLighting( False ),
m_bZWrite( True ),
m_bTransparency( False ),
m_TextureFilter( Mix::Graphics::TEXTURE_FILTER_POINT ),
m_TextureAddress( Mix::Graphics::TEXTURE_ADDRESS_WRAP ),
m_bReceiveShadow( False ),
m_bCastShadow( False ),
m_DiffuseType( Mix::Scene::IDefaultMaterial::DIFFUSE_LAMBERT ),
m_pDiffuseTexture( NULL ),
m_bDiffuseFresnel( False ),
m_bDiffuseRL( False ),
m_SpecularType( Mix::Scene::IDefaultMaterial::SPECULAR_NONE ),
m_pSpecularTexture( NULL ),
m_ReflectType( Mix::Scene::IDefaultMaterial::REFLECT_NONE ),
m_pEmissiveTexture( NULL ),
m_pBumpTexture( NULL ),
m_BumpType( Mix::Scene::IDefaultMaterial::BUMP_NORMAL ),
m_bWave( False ),
m_WaveType( Mix::Scene::IDefaultMaterial::WAVE_NORMAL ),
m_WaveDir( Mix::Scene::IDefaultMaterial::WAVE_NEGATIVE_U ),
m_bWaveInvert( False ),
m_WaveVelocity( 0.1f ),
m_WavePos( 0.0f ),
m_bRefract( False ),
m_bSoftParticle( False )
{
	UInt32 i;
	UInt32 j;

	for( i = 0; i < IMaterial::TR_MAX; i++ )
	{
		m_pVertexLayout[i] = NULL;

		for( j = 0; j < DefaultMaterial::RE_MAX; j++ )
		{
			m_pVertexShader[i][j] = NULL;
		}
	}

	for( i = 0; i < DefaultMaterial::RE_MAX; i++ )
	{
		m_pPixelShader[i] = NULL;
	}
}

DefaultMaterial::~DefaultMaterial( void )
{
	UInt32 i;
	UInt32 j;

	for( i = 0; i < IMaterial::TR_MAX; i++ )
	{
		MIX_RELEASE( m_pVertexLayout[i] );

		for( j = 0; j < DefaultMaterial::RE_MAX; j++ )
		{
			MIX_RELEASE( m_pVertexShader[i][j] );
		}
	}

	for( i = 0; i < DefaultMaterial::RE_MAX; i++ )
	{
		MIX_RELEASE( m_pPixelShader[i] );
	}

	MIX_RELEASE( m_pDiffuseTexture );
	MIX_RELEASE( m_pSpecularTexture );
	MIX_RELEASE( m_pEmissiveTexture );
	MIX_RELEASE( m_pBumpTexture );
}

Boolean DefaultMaterial::Initialize(	Mix::Graphics::IDevice* pDevice,
										Mix::Scene::Common::EffectPackage* pEffectPackage,
										Mix::IO::IReader* pReader,
										Boolean bWithMagicNumber,
										const wchar_t* pNameLabel,
										const wchar_t* pName,
										Mix::Scene::Standard::Common::DefaultMaterial* pMaterial )
{
	MIX_ASSERT( MIX_STR_LENGTH( pNameLabel ) > 0 );
	MIX_ASSERT( MIX_STR_LENGTH( pName ) > 0 );
	MIX_ASSERT( pReader != NULL );
	MIX_ASSERT( pEffectPackage != NULL );
	MIX_ASSERT( pDevice != NULL );
	MIX_ASSERT( pMaterial != NULL );

	Mix::STL::Vector<Mix::Memory::SECTION_SCENE, UInt8> tempBuff;

	DefaultMaterial::MTL_FILE_HEADER fileHeader;
	DefaultMaterial::MTL_INFO_HEADER_1_1_0_0 infoHeader;
	DefaultMaterial::MTL_DATA_HEADER_1_1_0_0 dataHeader;
	Mix::StringW texName;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ファイルヘッダを読み取る
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( bWithMagicNumber == True )
	{
		if( pReader->Read( &fileHeader, sizeof( fileHeader ) ) != sizeof( fileHeader ) )
		{
			MIX_LOG_ERROR( L"%s : %s[%s]", Mix::STR_ILLEGALFORMAT, pNameLabel, pName );
			return False;
		}

		if( fileHeader.magicNumber != DefaultMaterial::MTL_MAGIC_NUMBER )
		{
			MIX_LOG_ERROR( L"%s : %s[%s]", Mix::STR_ILLEGALFORMAT, pNameLabel, pName );
			return False;
		}
	}
	else
	{
		fileHeader.magicNumber = DefaultMaterial::MTL_MAGIC_NUMBER;

		if( pReader->Read( &( fileHeader.version ), sizeof( fileHeader.version ) ) != sizeof( fileHeader.version ) )
		{
			MIX_LOG_ERROR( L"%s : %s[%s]", Mix::STR_ILLEGALFORMAT, pNameLabel, pName );
			return False;
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// インフォヘッダ and データヘッダを読み取る
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( fileHeader.version == DefaultMaterial::MTL_VERSION_CUR )
	{
		if( pReader->Read( &infoHeader, sizeof( infoHeader ) ) != sizeof( infoHeader ) )
		{
			MIX_LOG_ERROR( L"%s : %s[%s]", Mix::STR_ILLEGALFORMAT, pNameLabel, pName );
			return False;
		}

		if( pReader->Read( &dataHeader, sizeof( dataHeader ) ) != sizeof( dataHeader ) )
		{
			MIX_LOG_ERROR( L"%s : %s[%s]", Mix::STR_ILLEGALFORMAT, pNameLabel, pName );
			return False;
		}
	}
	else
	{
		MIX_LOG_ERROR( L"バージョンが違います : %s[%s] FileVersion[0x%.08x] SupportVersion[0x%.08x]",
			pNameLabel,
			pName,
			fileHeader.version,
			DefaultMaterial::MTL_VERSION_CUR );

		return False;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// シェーダーを取得
	////////////////////////////////////////////////////////////////////////////////////////////////////

	EffectPackage::VERTEX_EFFECT* pSimpleVE;
	EffectPackage::VERTEX_EFFECT* pBlendVE;
	EffectPackage::PIXEL_EFFECT* pCommonPE;

	pSimpleVE = pEffectPackage->GetVertexEffectPtr( EffectPackage::E_MATERIAL, infoHeader.vertexShaderID[IMaterial::TR_SIMPLE] );
	pBlendVE = pEffectPackage->GetVertexEffectPtr( EffectPackage::E_MATERIAL, infoHeader.vertexShaderID[IDefaultMaterial::TR_SKINNING] );
	pCommonPE = pEffectPackage->GetPixelEffectPtr( EffectPackage::E_MATERIAL, infoHeader.pixelShaderID );

	if( ( ( pSimpleVE == NULL ) && ( pBlendVE == NULL ) ) ||
		( pCommonPE == NULL ) )
	{
		MIX_LOG_ERROR( L"シェーダーが見つかりません : Name[%s] %s[%s]", infoHeader.name, pNameLabel, pName );
		return False;
	}

	if( pSimpleVE != NULL )
	{
		MIX_ADD_REF( pSimpleVE->pLayout );
		pMaterial->m_pVertexLayout[IMaterial::TR_SIMPLE] = pSimpleVE->pLayout;

		MIX_ADD_REF( pSimpleVE->pShader[EffectPackage::VES_MATERIAL_COLOR] );
		pMaterial->m_pVertexShader[IMaterial::TR_SIMPLE][DefaultMaterial::RE_COLOR] = pSimpleVE->pShader[EffectPackage::VES_MATERIAL_COLOR];

		MIX_ADD_REF( pSimpleVE->pShader[EffectPackage::VES_MATERIAL_MASK] );
		pMaterial->m_pVertexShader[IMaterial::TR_SIMPLE][DefaultMaterial::RE_MASK] = pSimpleVE->pShader[EffectPackage::VES_MATERIAL_MASK];

		MIX_ADD_REF( pSimpleVE->pShader[EffectPackage::VES_MATERIAL_SHADOW] );
		pMaterial->m_pVertexShader[IMaterial::TR_SIMPLE][DefaultMaterial::RE_SHADOW] = pSimpleVE->pShader[EffectPackage::VES_MATERIAL_SHADOW];
	}

	if( pBlendVE != NULL )
	{
		MIX_ADD_REF( pBlendVE->pLayout );
		pMaterial->m_pVertexLayout[IMaterial::TR_SKINNING] = pBlendVE->pLayout;

		MIX_ADD_REF( pBlendVE->pShader[EffectPackage::VES_MATERIAL_COLOR] );
		pMaterial->m_pVertexShader[IMaterial::TR_SKINNING][DefaultMaterial::RE_COLOR] = pBlendVE->pShader[EffectPackage::VES_MATERIAL_COLOR];

		MIX_ADD_REF( pBlendVE->pShader[EffectPackage::VES_MATERIAL_MASK] );
		pMaterial->m_pVertexShader[IMaterial::TR_SKINNING][DefaultMaterial::RE_MASK] = pBlendVE->pShader[EffectPackage::VES_MATERIAL_MASK];

		MIX_ADD_REF( pBlendVE->pShader[EffectPackage::VES_MATERIAL_SHADOW] );
		pMaterial->m_pVertexShader[IMaterial::TR_SKINNING][DefaultMaterial::RE_SHADOW] = pBlendVE->pShader[EffectPackage::VES_MATERIAL_SHADOW];
	}

	if( pCommonPE != NULL )
	{
		MIX_ADD_REF( pCommonPE->pShader[EffectPackage::PES_MATERIAL_COLOR] );
		pMaterial->m_pPixelShader[DefaultMaterial::RE_COLOR] = pCommonPE->pShader[EffectPackage::PES_MATERIAL_COLOR];

		MIX_ADD_REF( pCommonPE->pShader[EffectPackage::PES_MATERIAL_MASK] );
		pMaterial->m_pPixelShader[DefaultMaterial::RE_MASK] = pCommonPE->pShader[EffectPackage::PES_MATERIAL_MASK];

		MIX_ADD_REF( pCommonPE->pShader[EffectPackage::PES_MATERIAL_SHADOW] );
		pMaterial->m_pPixelShader[DefaultMaterial::RE_SHADOW] = pCommonPE->pShader[EffectPackage::PES_MATERIAL_SHADOW];
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 共通のパラメータ
	////////////////////////////////////////////////////////////////////////////////////////////////////

	pMaterial->m_Name = infoHeader.name;

	pMaterial->m_ShaderType = static_cast<Mix::Scene::IDefaultMaterial::SHADER_TYPE>( dataHeader.shaderType );

	pMaterial->m_BlendType = static_cast<Mix::Graphics::BLEND_TYPE>( dataHeader.blendMode );

	pMaterial->m_CullType = ( MIX_TESTBIT( dataHeader.flags, DefaultMaterial::MTL_BACKCULLING ) == DefaultMaterial::MTL_BACKCULLING )? Mix::Graphics::CULL_BACK : Mix::Graphics::CULL_NONE;

	pMaterial->m_bBothFacesLighting = ( MIX_TESTBIT( dataHeader.flags, DefaultMaterial::MTL_BOTH_LIGHTING ) == DefaultMaterial::MTL_BOTH_LIGHTING );

	pMaterial->m_bTransparency = ( MIX_TESTBIT( dataHeader.flags, DefaultMaterial::MTL_TRANSPARENCY ) == DefaultMaterial::MTL_TRANSPARENCY );
	pMaterial->m_TransparencyMethod = static_cast<Mix::Scene::IMaterial::TRANSPARENCY_METHOD>( dataHeader.transparencyMethod );

	pMaterial->m_bZWrite = ( MIX_TESTBIT( dataHeader.flags, DefaultMaterial::MTL_ZWRITE ) == DefaultMaterial::MTL_ZWRITE );

	pMaterial->m_bReceiveShadow = ( MIX_TESTBIT( infoHeader.pixelShaderID, DefaultMaterial::MCF_SHADOW_RECEIVE )  && ( MIX_TESTBIT( dataHeader.flags, DefaultMaterial::MTL_SHADOW_RECEIVE ) == DefaultMaterial::MTL_SHADOW_RECEIVE ) );
	pMaterial->m_bCastShadow = ( MIX_TESTBIT( dataHeader.flags, DefaultMaterial::MTL_SHADOW_CAST ) == DefaultMaterial::MTL_SHADOW_CAST );

	pMaterial->m_TextureFilter = static_cast<Mix::Graphics::TEXTURE_FILTER_TYPE>( dataHeader.texFilterType );
	pMaterial->m_TextureAddress = static_cast<Mix::Graphics::TEXTURE_ADDRESS_TYPE>( dataHeader.texAddressType );

	pMaterial->m_DiffuseType = static_cast<Mix::Scene::IDefaultMaterial::DIFFUSE_TYPE>( dataHeader.diffuseType );
	pMaterial->m_bDiffuseFresnel = ( MIX_TESTBIT( dataHeader.flags, DefaultMaterial::MTL_DIFFUSE_FRESNEL ) == DefaultMaterial::MTL_DIFFUSE_FRESNEL );
	pMaterial->m_bDiffuseRL = ( MIX_TESTBIT( dataHeader.flags, DefaultMaterial::MTL_DIFFUSE_RIMLIGHTING ) == DefaultMaterial::MTL_DIFFUSE_RIMLIGHTING );

	pMaterial->m_SpecularType = static_cast<Mix::Scene::IDefaultMaterial::SPECULAR_TYPE>( dataHeader.specularType );

	pMaterial->m_ReflectType = static_cast<Mix::Scene::IDefaultMaterial::REFLECT_TYPE>( dataHeader.reflectType );

	pMaterial->m_BumpType = static_cast<Mix::Scene::IDefaultMaterial::BUMP_TYPE>( dataHeader.bumpType );

	pMaterial->m_bWave = ( MIX_TESTBIT( infoHeader.pixelShaderID, DefaultMaterial::MCF_WATER ) == DefaultMaterial::MCF_WATER );
	pMaterial->m_WaveType = static_cast<Mix::Scene::IDefaultMaterial::WAVE_TYPE>( dataHeader.waveType );
	pMaterial->m_WaveDir = static_cast<Mix::Scene::IDefaultMaterial::WAVE_DIR>( dataHeader.waveDir );
	pMaterial->m_bWaveInvert = ( MIX_TESTBIT( infoHeader.pixelShaderID, DefaultMaterial::MCF_WAVE_INVERT ) == DefaultMaterial::MCF_WAVE_INVERT );
	pMaterial->m_WaveVelocity = dataHeader.waveVelocity;

	pMaterial->m_bRefract = ( ( dataHeader.shaderType == Mix::Scene::IDefaultMaterial::SHADER_WATER ) && ( dataHeader.waveType == Mix::Scene::IDefaultMaterial::WAVE_REFRACT ) );

	pMaterial->m_bSoftParticle = ( ( MIX_TESTBIT( infoHeader.pixelShaderID, DefaultMaterial::MCF_SOFTPARTICLE ) && ( MIX_TESTBIT( dataHeader.flags, DefaultMaterial::MTL_SOFTPARTICLE ) == DefaultMaterial::MTL_SOFTPARTICLE ) ) );

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// 固有のパラメータ( シェーダー定数 )
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( pMaterial->BeginConstant() == True )
	{
		pMaterial->SetAmbientColor( Mix::Vector4( dataHeader.ambientColor[0], dataHeader.ambientColor[1], dataHeader.ambientColor[2] ) );

		pMaterial->SetDiffuseColor( Mix::Vector4( dataHeader.diffuseColor[0], dataHeader.diffuseColor[1], dataHeader.diffuseColor[2], dataHeader.diffuseColor[3] ) );
		pMaterial->SetDiffuseFresnelIntensity( dataHeader.diffuseFresnelRatio );
		pMaterial->SetDiffuseRLHardness( dataHeader.diffuseRLHardness );
		pMaterial->SetDiffuseRLScale( dataHeader.diffuseRLScale );

		pMaterial->SetSpecularColor( Mix::Vector4( dataHeader.specularColor[0], dataHeader.specularColor[1], dataHeader.specularColor[2], dataHeader.specularColor[3] ) );
		pMaterial->SetSpecularHardness( dataHeader.specularHardness );
		pMaterial->SetSpecularScale( dataHeader.specularScale );
		pMaterial->SetSpecularCTFresnel( dataHeader.specularCTFresnel );
		pMaterial->SetSpecularCTRoughness( dataHeader.specularCTRoughness );

		pMaterial->SetReflectScale( dataHeader.reflectScale );
		pMaterial->SetReflectIntensity( dataHeader.reflectIntensity );
		pMaterial->SetReflectBias( dataHeader.reflectBias );
		pMaterial->SetReflectExprosure( dataHeader.reflectExprosure );

		pMaterial->SetEmissiveColor( Mix::Vector4( dataHeader.emissiveColor[0], dataHeader.emissiveColor[1], dataHeader.emissiveColor[2], dataHeader.emissiveColor[3] ) );
		pMaterial->SetEmissiveScale( dataHeader.emissiveScale );

		pMaterial->SetBumpHeightScale( dataHeader.bumpHeightScale );
		pMaterial->SetBumpSampleCount( dataHeader.bumpSampleCount );
		pMaterial->SetBumpReflectFactor( dataHeader.bumpReflectRatio );

		pMaterial->SetWaveUVOffset( dataHeader.waveUVOffset );
		pMaterial->SetWaveGap( dataHeader.waveGap );

		pMaterial->SetWaveRefractiveIndex( dataHeader.refractRatio );

		pMaterial->SetSoftParticleThickness( dataHeader.particleThickness );

		pMaterial->EndConstant();
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ディフューズテクスチャを読み取る
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( MIX_TESTBIT( dataHeader.flags, DefaultMaterial::MTL_DIFFUSE_TEXTURE ) == MTL_DIFFUSE_TEXTURE )
	{
		texName.Sprintf( L"%s\\%s\\DiffuseTexture", pName, pMaterial->m_Name.GetConstPtr() );
		pMaterial->m_pDiffuseTexture = DefaultMaterial::CreateTexture( texName.GetConstPtr(), pDevice, pReader, tempBuff );
		if( pMaterial->m_pDiffuseTexture == NULL )
		{
			return False;
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// スペキュラーテクスチャを読み取る
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( MIX_TESTBIT( dataHeader.flags, DefaultMaterial::MTL_SPECULAR_TEXTURE ) == MTL_SPECULAR_TEXTURE )
	{
		texName.Sprintf( L"%s\\%s\\SpecularTexture", pName, pMaterial->m_Name.GetConstPtr() );
		pMaterial->m_pSpecularTexture = DefaultMaterial::CreateTexture( texName.GetConstPtr(), pDevice, pReader, tempBuff );
		if( pMaterial->m_pSpecularTexture == NULL )
		{
			return False;
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// エミッシブテクスチャを読み取る
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( MIX_TESTBIT( dataHeader.flags, DefaultMaterial::MTL_EMISSIVE_TEXTURE ) == MTL_EMISSIVE_TEXTURE )
	{
		texName.Sprintf( L"%s\\%s\\EmissiveTexture", pName, pMaterial->m_Name.GetConstPtr() );
		pMaterial->m_pEmissiveTexture = DefaultMaterial::CreateTexture( texName.GetConstPtr(), pDevice, pReader, tempBuff );
		if( pMaterial->m_pEmissiveTexture == NULL )
		{
			return False;
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// バンプテクスチャを読み取る
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( MIX_TESTBIT( dataHeader.flags, DefaultMaterial::MTL_BUMP_TEXTURE ) == MTL_BUMP_TEXTURE )
	{
		texName.Sprintf( L"%s\\%s\\BumpTexture", pName, pMaterial->m_Name.GetConstPtr() );
		pMaterial->m_pBumpTexture = DefaultMaterial::CreateTexture( texName.GetConstPtr(), pDevice, pReader, tempBuff );
		if( pMaterial->m_pBumpTexture == NULL )
		{
			return False;
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////

	return True;
}

Boolean DefaultMaterial::InternalClone( Mix::Scene::Standard::Common::DefaultMaterial* pMaterial )
{
	MIX_ASSERT( pMaterial != NULL );

	UInt32 i;
	UInt32 j;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// バーテックスレイアウト
	////////////////////////////////////////////////////////////////////////////////////////////////////

	for( i = 0; i < IMaterial::TR_MAX; i++ )
	{
		MIX_ADD_REF( m_pVertexLayout[i] );
		pMaterial->m_pVertexLayout[i] = m_pVertexLayout[i];
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// バーテックスシェーダー
	////////////////////////////////////////////////////////////////////////////////////////////////////

	for( i = 0; i < IMaterial::TR_MAX; i++ )
	{
		for( j = 0; j < DefaultMaterial::RE_MAX; j++ )
		{
			MIX_ADD_REF( m_pVertexShader[i][j] );
			pMaterial->m_pVertexShader[i][j] = m_pVertexShader[i][j];
		}
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// ピクセルシェーダー
	////////////////////////////////////////////////////////////////////////////////////////////////////

	for( i = 0; i < DefaultMaterial::RE_MAX; i++ )
	{
		MIX_ADD_REF( m_pPixelShader[i] );
		pMaterial->m_pPixelShader[i] = m_pPixelShader[i];
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// テクスチャ
	////////////////////////////////////////////////////////////////////////////////////////////////////

	MIX_ADD_REF( m_pDiffuseTexture );
	pMaterial->m_pDiffuseTexture = m_pDiffuseTexture;

	MIX_ADD_REF( m_pSpecularTexture );
	pMaterial->m_pSpecularTexture = m_pSpecularTexture;

	MIX_ADD_REF( m_pEmissiveTexture );
	pMaterial->m_pEmissiveTexture = m_pEmissiveTexture;

	MIX_ADD_REF( m_pBumpTexture );
	pMaterial->m_pBumpTexture = m_pBumpTexture;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// パラメータ
	////////////////////////////////////////////////////////////////////////////////////////////////////

	pMaterial->m_Name = m_Name;
	pMaterial->m_ShaderType = m_ShaderType;
	pMaterial->m_BlendType = m_BlendType;
	pMaterial->m_CullType = m_CullType;
	pMaterial->m_bBothFacesLighting = m_bBothFacesLighting;
	pMaterial->m_bTransparency = m_bTransparency;
	pMaterial->m_TransparencyMethod = m_TransparencyMethod;
	pMaterial->m_bZWrite = m_bZWrite;
	pMaterial->m_TextureFilter = m_TextureFilter;
	pMaterial->m_TextureAddress = m_TextureAddress;
	pMaterial->m_bReceiveShadow = m_bReceiveShadow;
	pMaterial->m_bCastShadow = m_bCastShadow;
	pMaterial->m_DiffuseType = m_DiffuseType;
	pMaterial->m_bDiffuseFresnel = m_bDiffuseFresnel;
	pMaterial->m_bDiffuseRL = m_bDiffuseRL;
	pMaterial->m_SpecularType = m_SpecularType;
	pMaterial->m_ReflectType = m_ReflectType;
	pMaterial->m_BumpType = m_BumpType;
	pMaterial->m_WaveType = m_WaveType;
	pMaterial->m_WaveDir = m_WaveDir;
	pMaterial->m_WaveVelocity = m_WaveVelocity;
	pMaterial->m_bRefract = m_bRefract;
	pMaterial->m_bSoftParticle = m_bSoftParticle;

	if( pMaterial->BeginConstant() == True )
	{
		pMaterial->SetAmbientColor( GetAmbientColor() );

		pMaterial->SetDiffuseColor( GetDiffuseColor() );
		pMaterial->SetDiffuseFresnelIntensity( GetDiffuseFresnelIntensity() );
		pMaterial->SetDiffuseRLHardness( GetDiffuseRLHardness() );
		pMaterial->SetDiffuseRLScale( GetDiffuseRLScale() );

		pMaterial->SetSpecularColor( GetSpecularColor() );
		pMaterial->SetSpecularHardness( GetSpecularHardness() );
		pMaterial->SetSpecularScale( GetSpecularScale() );
		pMaterial->SetSpecularCTFresnel( GetSpecularCTFresnel() );
		pMaterial->SetSpecularCTRoughness( GetSpecularCTRoughness() );

		pMaterial->SetReflectScale( GetReflectScale() );
		pMaterial->SetReflectIntensity( GetReflectIntensity() );
		pMaterial->SetReflectBias( GetReflectBias() );
		pMaterial->SetReflectExprosure( GetReflectExprosure() );

		pMaterial->SetEmissiveColor( GetEmissiveColor() );
		pMaterial->SetEmissiveScale( GetEmissiveScale() );

		pMaterial->SetBumpHeightScale( GetBumpHeightScale() );
		pMaterial->SetBumpSampleCount( GetBumpSampleCount() );
		pMaterial->SetBumpReflectFactor( GetBumpReflectFactor() );

		pMaterial->SetWaveUVOffset( GetWaveUVOffset() );

		pMaterial->SetWaveRefractiveIndex( GetWaveRefractiveIndex() );

		pMaterial->SetSoftParticleThickness( GetSoftParticleThickness() );

		pMaterial->EndConstant();
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////

	return True;
}

Mix::Vector2 DefaultMaterial::UpdateWave( Float32 dt )
{
	Mix::Vector2 ret = DefaultMaterial::WAVE_VEC_TABLE[m_WaveDir] * m_WavePos;

	m_WavePos += m_WaveVelocity * dt;
	if( m_WavePos >= 1.0f )
	{
		m_WavePos -= 1.0f;
	}

	return ret;
}

Mix::Graphics::ITexture* DefaultMaterial::CreateTexture( const wchar_t* pName, Mix::Graphics::IDevice* pDevice, Mix::IO::IReader* pReader, Mix::STL::Vector<Mix::Memory::SECTION_SCENE, UInt8>& tempBuff )
{
	MIX_ASSERT( MIX_STR_LENGTH( pName ) > 0 );
	MIX_ASSERT( pDevice != NULL );
	MIX_ASSERT( pReader != NULL );

	UInt32 texSize = 0;
	Mix::Graphics::ITexture* pTexture = NULL;

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// テクスチャのサイズを取得
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( pReader->Read( &texSize, sizeof( texSize ) ) != sizeof( texSize ) )
	{
		return NULL;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// テクスチャを読み取る
	////////////////////////////////////////////////////////////////////////////////////////////////////

	tempBuff.resize( texSize );

	if( pReader->Read( &( tempBuff[0] ), MIX_UIT_TO_UI32( tempBuff.size() ) ) != tempBuff.size() )
	{
		return NULL;
	}

	////////////////////////////////////////////////////////////////////////////////////////////////////
	// テクスチャインターフェースを作成
	////////////////////////////////////////////////////////////////////////////////////////////////////

	if( pDevice->CreateTextureFromMemory( pName, &( tempBuff[0] ), MIX_UIT_TO_UI32( tempBuff.size() ), &pTexture ) == False )
	{
		return NULL;
	}

	return pTexture;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::IDefaultMaterial : 全般
////////////////////////////////////////////////////////////////////////////////////////////////////

const wchar_t* DefaultMaterial::GetName( void ) const
{
	return m_Name.GetConstPtr();
}

Mix::Scene::IDefaultMaterial::SHADER_TYPE DefaultMaterial::GetShaderType( void ) const
{
	return m_ShaderType;
}

Mix::Graphics::BLEND_TYPE DefaultMaterial::GetBlendType( void ) const
{
	return m_BlendType;
}

void DefaultMaterial::SetBlendType( Mix::Graphics::BLEND_TYPE type )
{
	m_BlendType = type;
}

Mix::Graphics::CULL_TYPE DefaultMaterial::GetCullingType( void ) const
{
	return m_CullType;
}

void DefaultMaterial::SetCullingType( Mix::Graphics::CULL_TYPE type )
{
	m_CullType = type;
}

Boolean DefaultMaterial::IsZWrite( void ) const
{
	return m_bZWrite;
}

void DefaultMaterial::SetZWrite( Boolean state )
{
	m_bZWrite = state;
}

Mix::Graphics::TEXTURE_FILTER_TYPE DefaultMaterial::GetTextureFilterType( void ) const
{
	return m_TextureFilter;
}

void DefaultMaterial::SetTextureFilterType( Mix::Graphics::TEXTURE_FILTER_TYPE filter )
{
	m_TextureFilter = filter;
}

Mix::Graphics::TEXTURE_ADDRESS_TYPE DefaultMaterial::GetTextureAddressType( void ) const
{
	return m_TextureAddress;
}

void DefaultMaterial::SetTextureAddressType( Mix::Graphics::TEXTURE_ADDRESS_TYPE address )
{
	m_TextureAddress = address;
}

Boolean DefaultMaterial::IsBothFacesLighting( void ) const
{
	return m_bBothFacesLighting;
}

Boolean DefaultMaterial::IsReceiveShadow( void ) const
{
	return m_bReceiveShadow;
}

Boolean DefaultMaterial::IsCastShadow( void ) const
{
	return m_bCastShadow;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::IDefaultMaterial : ディフューズ
////////////////////////////////////////////////////////////////////////////////////////////////////

Mix::Scene::IDefaultMaterial::DIFFUSE_TYPE DefaultMaterial::GetDiffuseType( void ) const
{
	return m_DiffuseType;
}

Boolean DefaultMaterial::GetDiffuseTexture( Mix::Graphics::ITexture** ppTexture )
{
	if( m_pDiffuseTexture == NULL )
	{
		return False;
	}

	MIX_ADD_REF( m_pDiffuseTexture );
	( *ppTexture ) = m_pDiffuseTexture;

	return True;
}

Boolean DefaultMaterial::SetDiffuseTexture( Mix::Graphics::ITexture* pTexture )
{
	if( ( ( m_pDiffuseTexture != NULL ) && ( pTexture == NULL ) ) ||
		( ( m_pDiffuseTexture == NULL ) && ( pTexture != NULL ) ) )
	{
		return False;
	}

	MIX_RELEASE( m_pDiffuseTexture );
	MIX_ADD_REF( pTexture );
	m_pDiffuseTexture = pTexture;

	return True;
}

Boolean DefaultMaterial::IsDiffuseFresnel( void ) const
{
	return m_bDiffuseFresnel;
}

Boolean DefaultMaterial::IsDiffuseRL( void ) const
{
	return m_bDiffuseRL;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::IDefaultMaterial : スペキュラー( 全般 )
////////////////////////////////////////////////////////////////////////////////////////////////////

Mix::Scene::IDefaultMaterial::SPECULAR_TYPE DefaultMaterial::GetSpecularType( void ) const
{
	return m_SpecularType;
}

Boolean DefaultMaterial::GetSpecularTexture( Mix::Graphics::ITexture** ppTexture )
{
	if( m_pSpecularTexture == NULL )
	{
		return False;
	}

	MIX_ADD_REF( m_pSpecularTexture );
	( *ppTexture ) = m_pSpecularTexture;

	return True;
}

Boolean DefaultMaterial::SetSpecularTexture( Mix::Graphics::ITexture* pTexture )
{
	if( ( ( m_pSpecularTexture != NULL ) && ( pTexture == NULL ) ) ||
		( ( m_pSpecularTexture == NULL ) && ( pTexture != NULL ) ) )
	{
		return False;
	}

	MIX_RELEASE( m_pSpecularTexture );
	MIX_ADD_REF( pTexture );
	m_pSpecularTexture = pTexture;

	return True;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::IDefaultMaterial : スペキュラー( 反射 )
////////////////////////////////////////////////////////////////////////////////////////////////////

Mix::Scene::IDefaultMaterial::REFLECT_TYPE DefaultMaterial::GetReflectType( void ) const
{
	return m_ReflectType;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::IDefaultMaterial : エミッシブ
////////////////////////////////////////////////////////////////////////////////////////////////////

Boolean DefaultMaterial::GetEmissiveTexture( Mix::Graphics::ITexture** ppTexture )
{
	if( m_pEmissiveTexture == NULL )
	{
		return False;
	}

	MIX_ADD_REF( m_pEmissiveTexture );
	( *ppTexture ) = m_pEmissiveTexture;

	return True;
}

Boolean DefaultMaterial::SetEmissiveTexture( Mix::Graphics::ITexture* pTexture )
{
	if( ( ( m_pEmissiveTexture != NULL ) && ( pTexture == NULL ) ) ||
		( ( m_pEmissiveTexture == NULL ) && ( pTexture != NULL ) ) )
	{
		return False;
	}

	MIX_RELEASE( m_pEmissiveTexture );
	MIX_ADD_REF( pTexture );
	m_pEmissiveTexture = pTexture;

	return True;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::IDefaultMaterial : バンプ( 全般 )
////////////////////////////////////////////////////////////////////////////////////////////////////

Boolean DefaultMaterial::IsBump( void ) const
{
	return ( m_pBumpTexture != NULL );
}

Mix::Scene::IDefaultMaterial::BUMP_TYPE DefaultMaterial::GetBumpType( void ) const
{
	return m_BumpType;
}

Boolean DefaultMaterial::GetBumpTexture( Mix::Graphics::ITexture** ppTexture )
{
	if( m_pBumpTexture == NULL )
	{
		return False;
	}

	MIX_ADD_REF( m_pBumpTexture );
	( *ppTexture ) = m_pBumpTexture;

	return True;
}

Boolean DefaultMaterial::SetBumpTexture( Mix::Graphics::ITexture* pTexture )
{
	if( ( ( m_pBumpTexture != NULL ) && ( pTexture == NULL ) ) ||
		( ( m_pBumpTexture == NULL ) && ( pTexture != NULL ) ) )
	{
		return False;
	}

	MIX_RELEASE( m_pBumpTexture );
	MIX_ADD_REF( pTexture );
	m_pBumpTexture = pTexture;

	return True;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::IDefaultMaterial : バンプ( ウェーブ )
////////////////////////////////////////////////////////////////////////////////////////////////////

Boolean DefaultMaterial::IsWave( void ) const
{
	return m_bWave;
}

Mix::Scene::IDefaultMaterial::WAVE_TYPE DefaultMaterial::GetWaveType( void ) const
{
	return m_WaveType;
}

Mix::Scene::IDefaultMaterial::WAVE_DIR DefaultMaterial::GetWaveDir( void ) const
{
	return m_WaveDir;
}

void DefaultMaterial::SetWaveDir( Mix::Scene::IDefaultMaterial::WAVE_DIR dir )
{
	m_WaveDir = dir;
}

Boolean DefaultMaterial::IsWaveInvert( void ) const
{
	return m_bWaveInvert;
}

Float32 DefaultMaterial::GetWaveVelocity( void ) const
{
	return m_WaveVelocity;
}

void DefaultMaterial::SetWaveVelocity( Float32 vel )
{
	m_WaveVelocity = MIX_CLAMP( vel, 0.0f, 1.0f );
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::IDefaultMaterial : バンプ( 屈折効果 )
////////////////////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::IDefaultMaterial : パーティクル
////////////////////////////////////////////////////////////////////////////////////////////////////

Boolean DefaultMaterial::IsSoftParticle( void ) const
{
	return m_bSoftParticle;
}

////////////////////////////////////////////////////////////////////////////////////////////////////
// Mix::Scene::IMaterial
////////////////////////////////////////////////////////////////////////////////////////////////////

Mix::Scene::IMaterial::TYPE DefaultMaterial::GetType( void ) const
{
	return Mix::Scene::IMaterial::DEFAULT;
}

Boolean DefaultMaterial::IsTransformable( Mix::Scene::IMaterial::TRANSFORM_TYPE type ) const
{
	return True;
}

UInt32 DefaultMaterial::GetVertexStride( Mix::Scene::IMaterial::TRANSFORM_TYPE type ) const
{
	MIX_ASSERT( type < IMaterial::TR_MAX );
	return m_pVertexLayout[type]->GetStride();
}

UInt32 DefaultMaterial::GetVertexInputSigunature( Mix::Scene::IMaterial::TRANSFORM_TYPE type ) const
{
	MIX_ASSERT( type < IMaterial::TR_MAX );
	return m_pVertexLayout[type]->GetElementSemanticFlags();
}

Boolean DefaultMaterial::NeedsUpdate( void ) const
{
	return m_bWave;
}

Boolean DefaultMaterial::IsShadowing( void ) const
{
	return m_bCastShadow;
}

Boolean DefaultMaterial::IsLighting( void ) const
{
	return ( m_ShaderType != Mix::Scene::IDefaultMaterial::SHADER_SHADELESS );
}

Boolean DefaultMaterial::IsRefractive( void ) const
{
	return m_bRefract;
}

Boolean DefaultMaterial::IsTransparency( void ) const
{
	return m_bTransparency;
}

Mix::Scene::IMaterial::TRANSPARENCY_METHOD DefaultMaterial::GetTransparencyMethod( void ) const
{
	return m_TransparencyMethod;
}

void DefaultMaterial::RenderMask( Mix::Graphics::IDevice* pDevice, Mix::Scene::IMaterial::TRANSFORM_TYPE trType )
{
	pDevice->SetVertexLayout( m_pVertexLayout[trType] );
	pDevice->SetVertexShader( m_pVertexShader[trType][DefaultMaterial::RE_MASK] );
	pDevice->SetPixelShader( m_pPixelShader[DefaultMaterial::RE_MASK] );
}

}}}}
