#include "StdAfx.h"
#include "Fighter.h"

CFighter::CFighter(CDirect3D *d3d):
 C3DObject(d3d->g_pd3dDevice),
 SpeedX(0),
 SpeedY(0),
 SpeedZ(0.5),
 PositionX(0),
 PositionY(0),
 PositionZ(0),
 RotationZ(0),
 RotationX(0),
 Laser(0),
 LaserShow(false)
{
	this->d3d = d3d;
//	LoadFromFile ("fighter.3dp");
	LastTick = -1;

    ZeroMemory( &mtrl, sizeof(D3DMATERIAL9) );
    mtrl.Diffuse.r = mtrl.Ambient.r = 1.0f;
    mtrl.Diffuse.g = mtrl.Ambient.g = 1.0f;
    mtrl.Diffuse.b = mtrl.Ambient.b = 1.0f;
    mtrl.Diffuse.a = mtrl.Ambient.a = 1.0f;
    d3d->g_pd3dDevice->SetMaterial( &mtrl ); 
    ZeroMemory( &light, sizeof(D3DLIGHT9) );
	light.Type         = D3DLIGHT_SPOT;
	light.Theta        = 0.5f;
    light.Phi          = 1.0f;
    light.Falloff      = 1.0f;
    light.Attenuation0 = 1.0f;
    light.Diffuse.r    = 1.0f;
    light.Diffuse.g    = 1.0f;
    light.Diffuse.b    = 1.0f;
	light.Range        = 10.0f;
   
    d3d->g_pd3dDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
    d3d->g_pd3dDevice->SetRenderState( D3DRS_AMBIENT, 0x00202020 );

    if FAILED(D3DXLoadMeshFromX( "MyCraft.x", D3DXMESH_SYSTEMMEM, d3d->g_pd3dDevice, 
                       &m_pbufAdjacency, &m_pbufMaterials, NULL, &m_dwNumMaterials, 
					   &m_pMeshSysMem )) exit(-1);

	m_pMaterials = (D3DXMATERIAL *)m_pbufMaterials->GetBufferPointer();
    m_ppTextures = new LPDIRECT3DTEXTURE9[m_dwNumMaterials];

    for( UINT i=0; i<m_dwNumMaterials; i++ )
    {
		if ( m_pMaterials[i].pTextureFilename!=NULL)
		{
    	   if( FAILED( D3DXCreateTextureFromFile( d3d->g_pd3dDevice, m_pMaterials[i].pTextureFilename, 
                                               &m_ppTextures[i] ) ) ) exit(-1);
		}
		else
          m_ppTextures[i] = NULL;
    }

	LPDIRECT3DVERTEXBUFFER9 pVB = NULL;
	void*      pVertices = NULL;
	DWORD      pVSize = m_pMeshSysMem->GetNumBytesPerVertex();
	
    vertex_count = m_pMeshSysMem->GetNumVertices();
    faces_count = 0;
   
	device->CreateVertexBuffer(
 	 vertex_count * sizeof(Vertex),
	 D3DUSAGE_WRITEONLY,
	 Vertex::FVF,
	 D3DPOOL_MANAGED,
	 &VB,
	 0);
	IB = NULL;

    Vertex* vertices;
    VB->Lock(0, 0, (void**)&vertices, 0);
	
	 m_pMeshSysMem->GetVertexBuffer( &pVB );
     pVB->Lock( 0, 0, &pVertices, 0 );
     for (int i=0; i< vertex_count; i++)
	 {   
	  BasicVertex *v = (BasicVertex *)((char *)pVertices+pVSize*i);
  	  
	  vertices[i].position.x = v->x;
      vertices[i].position.y = v->y;
      vertices[i].position.z = v->z;
	 }
     pVB->Unlock();

	VB->Unlock();

	Scale (0.004f,0.004f,0.004f );
	Translate (-ObjectCenter().x,-ObjectCenter().y,0);
	Rotate (-D3DX_PI / 2, 0 , 0);
	Translate (-ObjectCenter().x,-ObjectCenter().y,0);
	
	RotationX = 0;
	RotationZ = 0;
	PositionX = 0;
	PositionY = 0;
	PositionZ = 0;

	Laser = new CLaser(d3d);
}

CFighter::~CFighter(void)
{
  
}

float DAbs(float x)
{
	return (x>=0)?x:-x;
}

float DSign(float x)
{
	if (x>0) return 1;
	if (x<0) return -1;
	if (x==0) return 0;
}

void D3DUtil_InitLight( D3DLIGHT9& light, D3DLIGHTTYPE ltType,
                        FLOAT x, FLOAT y, FLOAT z )
{
    D3DXVECTOR3 vecLightDirUnnormalized(x, y, z);
    ZeroMemory( &light, sizeof(D3DLIGHT9) );
    light.Type        = ltType;
    light.Diffuse.r   = 1.0f;
    light.Diffuse.g   = 1.0f;
    light.Diffuse.b   = 1.0f;
    D3DXVec3Normalize( (D3DXVECTOR3*)&light.Direction, &vecLightDirUnnormalized );
    light.Position.x   = x;
    light.Position.y   = y;
    light.Position.z   = z;
    light.Range        = 1000.0f;
}

void CFighter::Render()
{
  LastTick = GetTickCount();
  if( d3d->g_pd3dDevice )
  { 
    d3d->g_pd3dDevice->SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID);
    // Setup render state
    device->SetRenderState( D3DRS_LIGHTING,     TRUE );
    device->SetRenderState( D3DRS_DITHERENABLE, TRUE );

    // Setup the light
    D3DLIGHT9 light;
	D3DUtil_InitLight( light, D3DLIGHT_DIRECTIONAL, 0.0f, 1.0f, -2.0f );
    device->SetLight(0, &light );
    device->LightEnable(0, TRUE );
   
     for( UINT i = 0; i < m_dwNumMaterials; i++ )
        {
            device->SetMaterial( &m_pMaterials[i].MatD3D );
            device->SetTexture( 0, m_ppTextures[i] );

            m_pMeshSysMem->DrawSubset( i );
        }
   device->SetRenderState( D3DRS_LIGHTING,     FALSE );
   device->SetTexture( 0, NULL );

//   DrawLine(device, D3DXVECTOR3(0,-5,0)+ObjectCenter(),D3DXVECTOR3(0,5,0)+ObjectCenter());
//   DrawLine(device, D3DXVECTOR3(-5,0,0)+ObjectCenter(),D3DXVECTOR3(5,0,0)+ObjectCenter());

   if (LaserShow && Laser) Laser->Render();
  }  
}

void CFighter::IncreaseSpeed()
{
	SpeedZ += 0.003;
	if (SpeedZ > 1) SpeedZ = 0.999;
}

void CFighter::DecreaseSpeed()
{
	SpeedZ -= 0.003;
	if (SpeedZ < 0.5) SpeedZ = 0.5;
}
	
void CFighter::IncreaseRotation()
{
	SpeedX -= 0.003;
	if (SpeedX < -0.2f) SpeedX = -0.2f;
}

void CFighter::DecreaseRotation()
{
	SpeedX += 0.003;	
	if (SpeedX > 0.2f) SpeedX = 0.2f;
}

void CFighter::IncreaseHeight()
{
	if (SpeedY >= 0)
	{
	  SpeedY += 0.003*(1.0f - PositionY / 3.5f);		
	  if (SpeedY < 0) SpeedY = 0;
	  if (SpeedY > 0.2f) SpeedY = 0.2f;
	}
	else
	  SpeedY += 0.003;

}

void CFighter::DecreaseHeight()
{
	SpeedY -= 0.003;	
	if (SpeedY < -0.2f) SpeedY = -0.2f;
}


void CFighter::ComputeModel()
{
    DWORD Diff = 0;
	if (LastTick == -1){
		Diff = 0;
		LastTick = GetTickCount();
		return;
	}
	else{
		 Diff = GetTickCount() - LastTick;
		 if (Diff == 0) return;
	}
	LastTick = GetTickCount();   
  	
	float OldPosX = PositionX;
	float OldPosY = PositionY;
	Translate (-OldPosX,-OldPosY,0);	 
	 Rotate(-RotationX,0, -RotationZ);
	 Rotate(0,0, 0.5 * D3DX_PI * SpeedX / 0.2f);
	 Rotate(-0.125 * D3DX_PI * SpeedY / 0.2f,0, 0);
	Translate (OldPosX,OldPosY,0);

	//Move Craft		
	if (PositionY >= 7.5f && SpeedY > 0)
	{
		SpeedY = 0; //-0.003; 
        Translate (-SpeedX*SpeedZ/0.2f,-0.1,SpeedZ);		
	}
	else
        Translate (-SpeedX*SpeedZ/0.2f,SpeedY*(1.0f - PositionY / 7.5f)*SpeedZ/0.2f,SpeedZ);
	
	if (LaserShow)
	{
		Laser->Translate(0,0,LaserSpeed);
		LaserPosition.z += LaserSpeed;
		if (LaserPosition.z > 5*10) LaserShow = false;
	}

	D3DXMATRIX proj;
	D3DXMatrixPerspectiveFovLH(&proj, D3DX_PI * ( 0.5f  + 0.35*SpeedZ ), (float)1280 / (float) 1024, 0.5f, 1000.0f);
	d3d->g_pd3dDevice->SetTransform(D3DTS_PROJECTION, &proj);

}

void CFighter::Translate(float x, float y, float z)
{
	C3DObject::Translate (x,y,z);	
	PositionX += x;
	PositionY += y;
	PositionZ += z;

	D3DXVECTOR3 pos   = ObjectCenter();
	light.Position    = pos + D3DXVECTOR3( 0.0f, 5.0f, 0 ); 
    light.Direction   = D3DXVECTOR3( 0.0f, -1.0f, 0 );
	
	d3d->g_pd3dDevice->SetLight( 0, &light );
	d3d->g_pd3dDevice->LightEnable( 0, TRUE );
    
	LPDIRECT3DVERTEXBUFFER9 pVB = NULL;
	void*      pVertices = NULL;
	DWORD      pVSize = m_pMeshSysMem->GetNumBytesPerVertex();
	
	m_pMeshSysMem->GetVertexBuffer( &pVB );
    pVB->Lock( 0, 0, &pVertices, 0 );
     for (int i=0; i<m_pMeshSysMem->GetNumVertices(); i++)
	 {
		 BasicVertex *v = (BasicVertex *)((char *)pVertices+pVSize*i);
		 v->x += x;
		 v->y += y;
		 v->z += z;
	 }
    pVB->Unlock();
}

void CFighter::Scale(float sx, float sy, float sz)
{
    C3DObject::Scale (sx,sy,sz);

	LPDIRECT3DVERTEXBUFFER9 pVB = NULL;
	void*      pVertices = NULL;
	DWORD      pVSize = m_pMeshSysMem->GetNumBytesPerVertex();
	
	m_pMeshSysMem->GetVertexBuffer( &pVB );
    pVB->Lock( 0, 0, &pVertices, 0 );
     for (int i=0; i<m_pMeshSysMem->GetNumVertices(); i++)
	 {
		 BasicVertex *v = (BasicVertex *)((char *)pVertices+pVSize*i);
		 v->x *= sx;
		 v->y *= sy;
		 v->z *= sz;
	 }
    pVB->Unlock();
}

void CFighter::Rotate(float ax, float ay, float az)
{
    C3DObject::Rotate (ax,ay,az);

	D3DXMATRIX x,y,z,rez; 
	D3DXVECTOR3 vt,vt1;
	D3DXMatrixRotationX(&x,ax);
	D3DXMatrixRotationY(&y,ay);
	D3DXMatrixRotationZ(&z,az);
	rez = x*y*z;

	LPDIRECT3DVERTEXBUFFER9 pVB = NULL;
	void*      pVertices = NULL;
	DWORD      pVSize = m_pMeshSysMem->GetNumBytesPerVertex();
	
	m_pMeshSysMem->GetVertexBuffer( &pVB );
    pVB->Lock( 0, 0, &pVertices, 0 );
     for (int i=0; i<m_pMeshSysMem->GetNumVertices(); i++)
	 {         	     
		 BasicVertex *v = (BasicVertex *)((char *)pVertices+pVSize*i);
		 vt = D3DXVECTOR3(v->x,v->y,v->z);
		 D3DXVec3TransformCoord(&vt1,&vt,&rez);
		 v->x = vt1.x;
		 v->y = vt1.y;
		 v->z = vt1.z;
	 }
    pVB->Unlock();

	RotationZ += az;
	RotationX += ax;
}

IDirect3DVertexBuffer9 * CFighter::getVertexBuffer()
{
	LPDIRECT3DVERTEXBUFFER9 pVB = NULL;
	m_pMeshSysMem->GetVertexBuffer( &pVB );
	return pVB;
}

DWORD CFighter::getVertexCount()
{
	return m_pMeshSysMem->GetNumVertices();
}

DWORD CFighter::getBytesPerVertex()
{
	return m_pMeshSysMem->GetNumBytesPerVertex();
}

void CFighter::BeginShot()
{
 if (LaserShow) return;

 if (Laser) delete Laser;
 Laser = new CLaser(d3d);

 LaserShow = true;
 D3DXVECTOR3 pos = ObjectCenter();
 Laser->Translate(pos.x, pos.y, pos.z);
 LaserPosition = D3DXVECTOR3(0,0,0);
 LaserSpeed = SpeedX + 1.5;

}

void CFighter::EndShot()
{
  LaserShow = false;
}

double CFighter::ObjectSpeed()
{
	return SpeedZ;
}

double CFighter::GetZPosition()
{
	return PositionZ;
}