// Galaxy.cpp: implementation of the CGalaxy class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Galaxy.h"

#pragma pack(4)
typedef struct _STARVERTEX
{
	he3d_CVector			m_vPos;
	FLOAT					m_fSize;
} STARVERTEX, *PSTARVERTEX;
#pragma pack()

#define	FVF_STARVERTEX		D3DFVF_XYZ | D3DFVF_PSIZE

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CGalaxy::CGalaxy( PDIRECT3DDEVICE8 pDevice ) : CEfx( pDevice )
{
	m_pvbBackGnd = NULL;
	m_pvbGalaxy = NULL;
	m_pvbGalaxyStars = NULL;

	m_piqStar = NULL;
	m_piqFade = NULL;

	if( !CreateBox( m_pDevice, 1.0f, &m_pvbBackGnd ) )
		throw CSystemException( DEMO_EXCEPTION_D3DERROR, "unable to create background box" );

	ifstream				file;	

	file.open( "data\\extras\\galaxy.tmpl", ios::in|ios::binary );

	if( file.fail() )
		throw CSystemException( DEMO_EXCEPTION_FILENOTFOUND, "unable to open file galaxy.tmpl" );

	file.read( (LPBYTE)&m_dwGalaxyStarCount, sizeof(DWORD) );
	m_dwGalaxyStarCount = m_dwGalaxyStarCount/2;

	if( FAILED( m_pDevice->CreateVertexBuffer( m_dwGalaxyStarCount*sizeof(STARVERTEX), 0, FVF_STARVERTEX, D3DPOOL_DEFAULT, &m_pvbGalaxyStars ) ) )
		throw CSystemException( DEMO_EXCEPTION_FILENOTFOUND, "unable to galaxy create stars vertex buffer" );

	if( FAILED( m_pDevice->CreateVertexBuffer( 4*sizeof(LVERTEX), 0, FVF_LVERTEX, D3DPOOL_DEFAULT, &m_pvbGalaxy ) ) )
		throw CSystemException( DEMO_EXCEPTION_FILENOTFOUND, "unable to galaxy create galaxy vertex buffer" );

	PSTARVERTEX				pVertices;

	m_piqFade = new CImageQuad( m_pDevice );
	m_piqFade->SetColor( 0xffffff );
	m_piqStar = new CImageQuad( m_pDevice );
	m_piqStar->SetColor( 0xffffff );

	m_pvbGalaxyStars->Lock( 0, 0, (LPBYTE*)&pVertices, 0 );	

	for( DWORD i = 0 ; i < m_dwGalaxyStarCount/2 ; i++ )
	{
		FLOAT				pos[3];

		file.read( (LPBYTE)pos, 3*sizeof(FLOAT) );
		file.read( (LPBYTE)pos, 3*sizeof(FLOAT) );
		pVertices[i].m_vPos = he3d_CVector( pos[0], pos[1]*RAND(), pos[2] ) + he3d_CVector( 0.3f*SIGNEDRAND(), 0.0f, 0.3f*SIGNEDRAND() );
		pVertices[i].m_fSize = 0.1f + 0.1f*RAND();
	}

	pVertices[79].m_fSize = 0.5f;
	m_vTarget = pVertices[79].m_vPos;

	m_pvbGalaxyStars->Unlock();	

	PLVERTEX				pVerts;

	m_pvbGalaxy->Lock( 0, 0, (LPBYTE*)&pVerts, 0 );

	*(pVerts++) = LVERTEX( -5.0f, 0.0f, -5.0f, 0xffffff, 0.0f, 1.0f );
	*(pVerts++) = LVERTEX( -5.0f, 0.0f,  5.0f, 0xffffff, 0.0f, 0.0f );
	*(pVerts++) = LVERTEX(  5.0f, 0.0f, -5.0f, 0xffffff, 1.0f, 1.0f );
	*(pVerts++) = LVERTEX(  5.0f, 0.0f,  5.0f, 0xffffff, 1.0f, 0.0f );

	m_pvbGalaxy->Unlock();

	try
	{
		LoadTexture( "star.jpg" );
		LoadTexture( "deepspace.jpg" );
		LoadTexture( "galaxy.jpg" );
	}		
	catch( CTextureException )
	{
		throw CSystemException( DEMO_EXCEPTION_FILENOTFOUND, "unable to load textures" );
	}
}

CGalaxy::~CGalaxy()
{
	if( m_pvbBackGnd )
		m_pvbBackGnd->Release();

	if( m_pvbGalaxy )
		m_pvbGalaxy->Release();

	if( m_pvbGalaxyStars )
		m_pvbGalaxyStars->Release();

	if( m_piqStar )
		delete m_piqStar;

	if( m_piqFade )
		delete m_piqFade;
}

BOOL CGalaxy::InitEfx()
{
	return TRUE;
}

BOOL CGalaxy::FinishEfx()
{
	return TRUE;
}

BOOL CGalaxy::UpdateFrame( FLOAT fTime )
{
	m_pDevice->SetTransform( D3DTS_VIEW, CameraMtx( he3d_CVector( 0, 1.5, -3 ), he3d_CVector( 0, 0, 0 ), 0 ) );
	m_pDevice->SetTransform( D3DTS_PROJECTION, ProjectionMtx( 60.0f - 3.0f*fTime, 1.25f, 0.1f, 1000.0f ) );	

	he3d_CVector			pos = he3d_CVector( 0, 1.5f, -3 )*ScaleMtx( 2.0f - 0.05f*fTime ) *YRotationMtx( 0.1f*fTime );
	he3d_CVector			trg = m_vTarget*YRotationMtx( -0.2f*fTime )*ScaleMtx( 0.5f );

	m_mtxCamera = CameraMtx( pos, trg, 0 );

	m_mtxGalaxy = YRotationMtx( -0.2f*fTime )*ScaleMtx( 0.5f );

	FLOAT					fAlpha = 0.0f;

	if( fTime < 2.0f )
	{
		fAlpha = (2.0f - fTime)*128.0f;
			
		if( fAlpha < 0.0f )
			fAlpha = 0.0f;
		else if( fAlpha > 255.0f )
			fAlpha = 255.0f;
	}

	if( fTime > 18.0f )
	{
		fAlpha = (fTime - 18.0f)*128.0f;
			
		if( fAlpha < 0.0f )
			fAlpha = 0.0f;
		else if( fAlpha > 255.0f )
			fAlpha = 255.0f;
	}	

	m_piqFade->SetAlpha( (DWORD)fAlpha );

	m_bRenderStar = FALSE;

	if( fTime > 18.0f )
	{
		fAlpha = (fTime - 18.0f)*300.0f;

		m_piqStar->Resize( 320.0f - fAlpha, 240.0f - fAlpha, 320.0f + fAlpha, 240.0f + fAlpha );
		m_bRenderStar = TRUE;
	}	

	return TRUE;
}

BOOL CGalaxy::RenderEfx()
{		
	m_pDevice->SetTransform( D3DTS_VIEW, m_mtxCamera );

	m_pDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
	m_pDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
	m_pDevice->SetRenderState( D3DRS_ZENABLE, FALSE );
	m_pDevice->SetTexture( 0, GetTexture( "deepspace.jpg" ) );
	m_pDevice->SetVertexShader( FVF_LVERTEX );
	m_pDevice->SetStreamSource( 0, m_pvbBackGnd, sizeof(LVERTEX) );
	m_pDevice->SetTransform( D3DTS_WORLD, ScaleMtx( 10.0f ) );
	m_pDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, 12 );

	m_pDevice->SetRenderState( D3DRS_POINTSPRITEENABLE, TRUE );
	m_pDevice->SetRenderState( D3DRS_POINTSCALEENABLE, TRUE );
	m_pDevice->SetRenderState( D3DRS_POINTSCALE_A, FLT2DWORD( 1.0f ) );
	m_pDevice->SetRenderState( D3DRS_POINTSCALE_B, FLT2DWORD( 1.0f ) );
	m_pDevice->SetRenderState( D3DRS_POINTSCALE_C, FLT2DWORD( 1.0f ) );
	m_pDevice->SetRenderState( D3DRS_POINTSIZE_MAX, FLT2DWORD( 1000.0f ) );
	m_pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
	m_pDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_ONE );
	m_pDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );

	m_pDevice->SetTransform( D3DTS_WORLD, m_mtxGalaxy );

	m_pDevice->SetTexture( 0, GetTexture( "star.jpg" ) );

	m_pDevice->SetVertexShader( FVF_STARVERTEX );
	m_pDevice->SetStreamSource( 0, m_pvbGalaxyStars, sizeof(STARVERTEX) );
	m_pDevice->DrawPrimitive( D3DPT_POINTLIST, 0, m_dwGalaxyStarCount );

	m_pDevice->SetRenderState( D3DRS_POINTSCALEENABLE, FALSE );

	m_pDevice->SetTexture( 0, GetTexture( "galaxy.jpg" ) );
 
	m_pDevice->SetVertexShader( FVF_LVERTEX );
	m_pDevice->SetStreamSource( 0, m_pvbGalaxy, sizeof( LVERTEX ) );
	m_pDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );	

	if( m_bRenderStar )
	{
		m_pDevice->SetTexture( 0, GetTexture( "star.jpg" ) );
		m_piqStar->Render( m_pDevice );
	}

	m_pDevice->SetTexture( 0, NULL );
	m_pDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
	m_pDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );

	m_piqFade->Render( m_pDevice );

	m_pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );

	return TRUE;
}
