#include "CXLoader.h"

#define PI 3.1415926535897932384626433832795   


CXLoader::CXLoader()
{
	m_pMesh          = NULL; // Our mesh object in sysmem
	m_pMeshMaterials = NULL; // Materials for our mesh
	m_pMeshTextures  = NULL; // Textures for our mesh
	m_dwNumMaterials = 0L;   // Number of mesh materials
	m_pD3DDevice      = NULL;
 


	D3DXMatrixIdentity(&m_matRot);
	D3DXMatrixTranslation(&m_matPos, 0.0f, 0.0f, 0.0f);
    D3DXMatrixScaling(&m_scale3, 0.25f, 0.25f, 0.25f);
	D3DXMatrixScaling(&m_scale2, 0.20f, 0.20f, 0.20f);
	D3DXMatrixScaling(&m_scale1, 0.15f, 0.15f, 0.15f);
	D3DXMatrixScaling(&m_scale0, 0.03f, 0.03f, 0.03f);
}
void CXLoader::cam()
{
	  D3DXVECTOR3 eye(0,0,400);
      D3DXVECTOR3 at(0,0,0);
      D3DXVECTOR3 up(0,1,0);
      D3DXMatrixLookAtRH(&out, &eye, &at, &up);
}
void CXLoader::Create(IDirect3DDevice8** pD3DDevice, char *szFilename, char *TexturePath = ".\\")
{
	HRESULT hRes = D3D_OK;
	m_pD3DDevice = *pD3DDevice;
 
	LPD3DXBUFFER pD3DXMtrlBuffer = NULL;
 	// Load the mesh from the specified file
	hRes = D3DXLoadMeshFromX( szFilename, D3DXMESH_SYSTEMMEM, 
                       m_pD3DDevice, NULL, 
                       &pD3DXMtrlBuffer, &m_dwNumMaterials, 
                       &m_pMesh );
    if(FAILED(hRes)) return;
	// We need to extract the material properties and texture names from the 
	// pD3DXMtrlBuffer
	D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)pD3DXMtrlBuffer->GetBufferPointer();
	m_pMeshMaterials = new D3DMATERIAL8[m_dwNumMaterials];
	m_pMeshTextures  = new LPDIRECT3DTEXTURE8[m_dwNumMaterials];
 
	for( DWORD i=0; i<m_dwNumMaterials; i++ )
	{
		// Copy the material
		m_pMeshMaterials[i] = d3dxMaterials[i].MatD3D;
 
		// Set the ambient color for the material (D3DX does not do this)
		m_pMeshMaterials[i].Ambient = m_pMeshMaterials[i].Diffuse;
 
		m_pMeshTextures[i] = NULL;
 
		if(d3dxMaterials[i].pTextureFilename != NULL)
		{
			char szTextureFile[256];
			strcpy(szTextureFile, TexturePath);
			strcat(szTextureFile, d3dxMaterials[i].pTextureFilename);
 
			// Create the texture
/*			if( FAILED( D3DXCreateTextureFromFile( m_pD3DDevice, 
                                                   szTextureFile, &m_pMeshTextures[i] ) ) )*/
 if(FAILED(D3DXCreateTextureFromFileEx(m_pD3DDevice, szTextureFile, 0, 0, 0, 0,
                                          D3DFMT_UNKNOWN, D3DPOOL_MANAGED, D3DX_DEFAULT,
                                          D3DX_DEFAULT, 0, NULL, NULL, &m_pMeshTextures[i])))
			{
				m_pMeshTextures[i] = NULL;
			}
		}
	}
	// Done with the material buffer
	pD3DXMtrlBuffer->Release();
	m_x = m_y = m_z = m_xRot = m_yRot = m_zRot = 0.0f;
}
void CXLoader::MoveX(float x)
{
	m_x = x;
	D3DXMatrixTranslation(&m_matPos, m_x, m_y, m_z);
}

void CXLoader::MoveY(float y)
{
	m_y = y;
	D3DXMatrixTranslation(&m_matPos, m_x, m_y, m_z);
}

void CXLoader::Move(float x, float y, float z)
{
	m_x = x;
	m_y = y;
	m_z = z;
 
	D3DXMatrixTranslation(&m_matPos, m_x, m_y, m_z);
}
 
void CXLoader::MoveRel(float x, float y, float z)
{
	m_x += x;
	m_y += y;
	m_z += z;
 
	D3DXMatrixTranslation(&m_matPos, m_x, m_y, m_z);
}
 
float CXLoader::GetXpos()
{
	return m_x;
}
float CXLoader::GetYpos()
{
	return m_y;
}
float CXLoader::GetZpos()
{
	return m_z;
}
 
void CXLoader::Rotate(float x_rot, float y_rot, float z_rot)
{
	m_xRot = x_rot;
	m_yRot = y_rot;
	m_zRot = z_rot;
	if(m_zRot < 0)
		m_zRot = (2.0*PI) - .000001;
    if(m_zRot > (2.0*PI))
		m_zRot = 0;
 
		D3DXMATRIX mX, mY, mZ;
		D3DXMatrixRotationX(&mX, x_rot);
		D3DXMatrixRotationY(&mY, y_rot);
		D3DXMatrixRotationZ(&mZ, z_rot);
 
		m_matRot = mX;
		D3DXMatrixMultiply(&m_matRot, &m_matRot, &mY);
		D3DXMatrixMultiply(&m_matRot, &m_matRot, &mZ);
}
void CXLoader::RotateRel(float x_rot, float y_rot, float z_rot)
{
	m_xRot += x_rot;
	m_yRot += y_rot;
	m_zRot += z_rot;
 
	if(m_zRot < 0)
		m_zRot = (2.0*PI) - .000001;
    if(m_zRot > (2.0*PI))
		m_zRot = 0;

		D3DXMATRIX mX, mY, mZ;
		D3DXMatrixRotationX(&mX, m_xRot);
		D3DXMatrixRotationY(&mY, m_yRot);
		D3DXMatrixRotationZ(&mZ, m_zRot);
 
		m_matRot = mX;
		D3DXMatrixMultiply(&m_matRot, &m_matRot, &mY);
		D3DXMatrixMultiply(&m_matRot, &m_matRot, &mZ);
}
float CXLoader::GetXrot()
{
	return m_xRot;
}
float CXLoader::GetYrot()
{
	return m_yRot;
}
float CXLoader::GetZrot()
{
	return m_zRot;
}
void CXLoader::scale(int size)
{
  switch(size)
  {
      case -1:
		 D3DXMatrixMultiply(&m_matWorld, &m_matWorld, &m_scale0);
	     break;
	  case 0:
		  break;
	  case 1:
	     D3DXMatrixMultiply(&m_matWorld, &m_matWorld, &m_scale1);
		 break;
	  case 2:
	     D3DXMatrixMultiply(&m_matWorld, &m_matWorld, &m_scale2);
		 break;
	  case 3:
	     D3DXMatrixMultiply(&m_matWorld, &m_matWorld, &m_scale3);
		 break;
	  default:
	  break;
  }

}
void CXLoader::Render(int size)
{
/*
	D3DXMatrixMultiply(&m_matWorld, &m_matWorld, &m_matRot);
 
	m_pD3DDevice->SetTransform( D3DTS_WORLD, &m_matWorld);
*/
 
	m_matWorld = m_matRot;
	D3DXMatrixMultiply(&m_matWorld, &m_matWorld, &m_matPos);
	scale(size);
	m_pD3DDevice->SetTransform( D3DTS_WORLD, &m_matWorld);
	/*cam();
	D3DXMatrixMultiply(&out, &out, &m_matPos);
	D3DXMatrixMultiply(&out, &out, &m_scale);
	m_pD3DDevice->SetTransform( D3DTS_VIEW, &out);
*/
/*
	D3DXMATRIX matProj;
    D3DXMatrixPerspectiveFovLH(&matProj, D3DX_PI/4, 1.0f, 1.0f, 30.0f);
    m_pD3DDevice->SetTransform(D3DTS_PROJECTION, &matProj);

	//Combine out matrices
	D3DXMatrixMultiply(&m_matWorld,&m_matWorld, &m_matPos);
	//Set our World Matrix
	m_pD3DDevice->SetTransform(D3DTS_WORLD, &m_matWorld );
*/
	// Turn on ambient lighting 
//	m_pD3DDevice->SetRenderState( D3DRS_AMBIENT, 0x00606060 );
 
	m_pD3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
 
	// goraud shading
	m_pD3DDevice->SetRenderState(D3DRS_SHADEMODE, D3DSHADE_GOURAUD);
	m_pD3DDevice->SetRenderState(D3DRS_SPECULARENABLE, TRUE);
 
	// Meshes are divided into subsets, one for each material. Render them in
	// a loop
	m_pD3DDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, FALSE);
 
	m_pD3DDevice->SetRenderState(D3DRS_LIGHTING, FALSE);
 
	for( DWORD i=0; i<m_dwNumMaterials; i++ )
	{
		// Set the material and texture for this subset
		m_pD3DDevice->SetMaterial( &m_pMeshMaterials[i] );
 
		if( m_pMeshTextures[i] != NULL )
		{
			m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
			m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
			m_pD3DDevice->SetTexture( 0, m_pMeshTextures[i] );
		}else{
			m_pD3DDevice->SetTexture( 0, NULL );
			m_pD3DDevice->SetRenderState(D3DRS_LIGHTING, TRUE);
			m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
			m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE );//D3DTA_SPECULAR); //D3DTA_DIFFUSE
		}
 
		// Draw the mesh subset
		m_pMesh->DrawSubset( i );
	}
 
	m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_SELECTARG1);
	m_pD3DDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE);
}
 
void CXLoader::Release()
{
	if( m_pMeshMaterials != NULL ) 
		delete[] m_pMeshMaterials;
	if( m_pMeshTextures )
	{
		for( DWORD i = 0; i < m_dwNumMaterials; i++ )
		{
			if( m_pMeshTextures[i] )
				m_pMeshTextures[i]->Release();
		}
		delete[] m_pMeshTextures;
	}
	if( m_pMesh != NULL )
		m_pMesh->Release();
}