// TitleScreen.cpp: implementation of the CTitleScreen class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "TitleScreen.h"

#define	BASEXSIZE		200.0f
#define	BASEYSIZE		100.0f

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

VOID Merge( DWORD dwSet1Count, he3d_CVector* pvSet1, DWORD& dwSet2Count, he3d_CVector* pvSet2 )
{
	#define VECEQU( a, b ) ( fabsf( (a).x - (b).x ) < H_EPSILON && fabsf( (a).y - (b).y ) < H_EPSILON && fabsf( (a).z - (b).z ) < H_EPSILON )

	BOOL					bFound;

	for( DWORD i = 0 ; i < dwSet1Count ; i+=2 )
	{
		bFound = FALSE;

		for( DWORD j = 0 ; j < dwSet2Count ; j+=2 )
		{
			if( ( VECEQU( pvSet1[i], pvSet2[j] ) && VECEQU( pvSet1[i+1], pvSet2[j+1] ) ) || ( VECEQU( pvSet1[i], pvSet2[j+1] ) && VECEQU( pvSet1[i+1], pvSet2[j] ) ) )
			{
				bFound = TRUE;
				break;
			}
		}

		if( !bFound )
		{
			pvSet2[dwSet2Count++] = pvSet1[i];
			pvSet2[dwSet2Count++] = pvSet1[i+1];
		}
	}
}

CTitleScreen::CTitleScreen( PDIRECT3DDEVICE8 pDevice ) : CEfx( pDevice )
{
	m_ptext = new CTextureRenderer( m_pDevice );
		
	try
	{
		LoadTexture( "red.jpg" );
		LoadTexture( "envmap4.jpg" );
		LoadTexture( "crack.jpg" );
		LoadTexture( "flash.jpg" );

		LoadTexture( "shism00.jpg" );
		LoadTexture( "shism01.jpg" );
		LoadTexture( "shism02.jpg" );
		LoadTexture( "shism03.jpg" );
		LoadTexture( "shism04.jpg" );
		

		for( INT i = 0 ; i < 32 ; i++ )
		{
			TCHAR			name[] = "caust00.bmp";
			_stprintf( name, "caust%02i.bmp", i );

			LoadAlphaTexture( name );
			m_pptextAlpha[i] = GetTexture( name );
		}
	}
	catch( CTextureException )
	{
		throw CSystemException( DEMO_EXCEPTION_FILENOTFOUND, "unable to load textures" );
	}
	
	m_pptextMips[0] = GetTexture( "shism00.jpg" );
	m_pptextMips[1] = GetTexture( "shism01.jpg" );
	m_pptextMips[2] = GetTexture( "shism02.jpg" );
	m_pptextMips[3] = GetTexture( "shism03.jpg" );
	m_pptextMips[4] = GetTexture( "shism04.jpg" );

	m_fAlpha = 0.0f;
	m_dwTextIndex = 0;
	m_dwAlphaIndex = 0;	
	m_bRenderFlash = FALSE;
	m_bRenderFade = FALSE;

	m_piqTitle = new CImageQuad( m_pDevice );
	m_piqFlash = new CImageQuad( m_pDevice );
	m_piqFlash->SetColor( 0xff0000 );
	m_piqTitle->SetColor( 0x0 );

	m_pmS = new CSimpleMesh();
	m_pmLogo = new CSimpleMesh();

	if( !m_pmS->Load( m_pDevice, "data\\objects\\s.smf" ) )
		throw CSystemException( DEMO_EXCEPTION_FILENOTFOUND, "unable to load s.smf" );

	if( !m_pmLogo->Load( m_pDevice, "data\\objects\\logo.smf" ) )
		throw CSystemException( DEMO_EXCEPTION_FILENOTFOUND, "unable to load logo.smf" );

	for( DWORD i = 0 ; i < 10 ; i++ )
	{
		TCHAR			name[] = "data\\objects\\mirror00.smf";
		_stprintf( name, "data\\objects\\mirror%02i.smf", i );

		if( !m_mMirror[i].Load( m_pDevice, name ) )
			throw CSystemException( DEMO_EXCEPTION_FILENOTFOUND, "unable to load mirrorxx.smf" );

		m_mtxMirror[i] = IdentMtx();
	}

	for( i = 0 ; i < 5 ; i++ )
	{
		TCHAR			name[] = "data\\objects\\piece00.smf";
		_stprintf( name, "data\\objects\\piece%02i.smf", i );

		if( !m_mPiece[i].Load( m_pDevice, name ) )
			throw CSystemException( DEMO_EXCEPTION_FILENOTFOUND, "unable to load piecexx.smf" );
	}

	// crack initialization

	PFACECONECTIVITYDATA	pFC;
	he3d_CVector			vTmpShiluette[500];
	he3d_CVector			vFinalShiluette[2000];
	DWORD					dwTmpShiluetteCount;
	DWORD					dwFinalShiluetteCount = 0;
	
	for( i = 0 ; i < 10 ; i++ )
	{	
		CalculateConectivity( m_mMirror[i], pFC );	
		CreateShiluette( m_mMirror[i], pFC, IdentMtx(), dwTmpShiluetteCount, vTmpShiluette );

		delete pFC;

		Merge( dwTmpShiluetteCount, vTmpShiluette, dwFinalShiluetteCount, vFinalShiluette );
	}

	for( i = 0 ; i < 5 ; i++ )
	{
		CalculateConectivity( m_mPiece[i], pFC );	
		CreateShiluette( m_mPiece[i], pFC, IdentMtx(), dwTmpShiluetteCount, vTmpShiluette );

		if( FAILED( m_pDevice->CreateVertexBuffer( dwTmpShiluetteCount*3*sizeof(SIMPLEVERTEX), 0, FVF_SIMPLEVERTEX, D3DPOOL_DEFAULT, &m_pvbVolumetic[i] ) ) )
			throw CSystemException( DEMO_EXCEPTION_D3DERROR, "unable to create volume vertex buffer" );

		if( FAILED( m_pDevice->CreateVertexBuffer( m_mPiece[i].GetVertexCount()*50*sizeof(SIMPLEVERTEX), 0, FVF_SIMPLEVERTEX, D3DPOOL_DEFAULT, &m_pvbInnerVolumetric[i] ) ) )
			throw CSystemException( DEMO_EXCEPTION_D3DERROR, "unable to create inner volume vertex buffer" );

		if( FAILED( m_pDevice->CreateIndexBuffer( m_mPiece[i].GetFacesCount()*150*sizeof(WORD), 0, D3DFMT_INDEX16, D3DPOOL_DEFAULT, &m_pibInnerVolumetric[i] ) ) )
			throw CSystemException( DEMO_EXCEPTION_D3DERROR, "unable to create inner volume index buffer" );

		PVERTEX				pPieceVertices;
		LPWORD				pPieceIndices;		
		PSIMPLEVERTEX		pV;
		LPWORD				pIndices;
		
		m_mPiece[i].LockMesh( (LPBYTE*)&pPieceVertices, (LPBYTE*)&pPieceIndices );
		m_pvbInnerVolumetric[i]->Lock( 0, 0, (LPBYTE*)&pV, 0 );
		m_pibInnerVolumetric[i]->Lock( 0, 0, (LPBYTE*)&pIndices, 0 );

		for( DWORD j = 0 ; j < 50 ; j++ )
		{		
			for( DWORD k = 0 ; k < m_mPiece[i].GetVertexCount() ; k++ )			
				pV[j*m_mPiece[i].GetVertexCount()+k] = SIMPLEVERTEX( pPieceVertices[k].m_vPos - he3d_CVector( 0, 0, (FLOAT)j ), D3DCOLOR_ARGB( 0x5, 0xff, 0x00, 0x00 ) );
			
			for( k = 0 ; k < 3*m_mPiece[i].GetFacesCount() ; k++ )			
				pIndices[j*m_mPiece[i].GetFacesCount()*3+k] = pPieceIndices[k] + (WORD)(j*m_mPiece[i].GetVertexCount());			
		}

		m_mPiece[i].UnlockMesh();
		m_pvbInnerVolumetric[i]->Unlock();
		m_pibInnerVolumetric[i]->Unlock();
		
		m_pvbVolumetic[i]->Lock( 0, 0, (LPBYTE*)&pV, 0 );
		CreateParallelVolumeFromShiluette( dwTmpShiluetteCount, vTmpShiluette, he3d_CVector( 0, 0, -1), sizeof(SIMPLEVERTEX), (LPBYTE)pV );

		for( j = 0 ; j < 3*dwTmpShiluetteCount ; j++ )
			pV[j].m_dwColor = 0x80800000;

		m_pvbVolumetic[i]->Unlock();

		m_dwVolumeFaces[i] = dwTmpShiluetteCount;

		delete pFC;

		Merge( dwTmpShiluetteCount, vTmpShiluette, dwFinalShiluetteCount, vFinalShiluette );
	}	

	if( FAILED( m_pDevice->CreateVertexBuffer( 3*dwFinalShiluetteCount*sizeof(LVERTEX), 0, FVF_LVERTEX, D3DPOOL_DEFAULT, &m_pvbCrack ) ) )
		throw CSystemException( DEMO_EXCEPTION_D3DERROR, "unable to create crack mesh vertex buffer" );

	PLVERTEX				pVertices;

	m_pvbCrack->Lock( 0, 0, (LPBYTE*)&pVertices, 0 );
	for( i = 0 ; i < dwFinalShiluetteCount ; i += 2 )
	{
		*(pVertices++) = LVERTEX( vFinalShiluette[i], 0xffffff, 0.0f, 0.9f );
		*(pVertices++) = LVERTEX( vFinalShiluette[i] + he3d_CVector( 0, 0, -0.05f ), 0xffffff, 0.0f, 0.1f );
		*(pVertices++) = LVERTEX( vFinalShiluette[i+1], 0xffffff, 1.0f, 0.9f );

		*(pVertices++) = LVERTEX( vFinalShiluette[i] + he3d_CVector( 0, 0, -0.05f ), 0xffffff, 0.0f, 0.1f );
		*(pVertices++) = LVERTEX( vFinalShiluette[i+1] + he3d_CVector( 0, 0, -0.05f ), 0xffffff, 1.0f, 0.1f );
		*(pVertices++) = LVERTEX( vFinalShiluette[i+1], 0xffffff, 1.0f, 0.9f );
	}
	m_pvbCrack->Unlock();

	m_dwCrackFaces = dwFinalShiluetteCount;
}

CTitleScreen::~CTitleScreen()
{	
	delete m_piqTitle;
	delete m_pmS;
	delete m_pmLogo;
	delete m_ptext;
}

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

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

BOOL CTitleScreen::UpdateFrame( FLOAT fTime )
{		

	for( INT i = 0 ; i < 5 ; i++ )
	{
		m_mtxPiece[i] = ScaleMtx( 1.42f, 1.07f, 1.0f )*TranslationMtx( 0, 0, 5 );
		m_fVolumeLen[i] = 0.0f;
		m_bRenderVolume[i] = FALSE;
	}

	m_bRenderCrack = TRUE;

	m_dwTextIndex = 0;
	m_piqTitle->SetAlpha( 0x0 );

	m_dwAlphaIndex = (DWORD)(fTime*17.0f);
	m_dwAlphaIndex %= 32;	
	
	FLOAT					fAmpl = fTime*25.0f;

	if( fAmpl > 50.0f )
		fAmpl = 50.0f;

	m_fAlpha = 128.0f*fTime;

	if( m_fAlpha > 255.0f )
		m_fAlpha = 255.0f;

	m_fAlpha -= fAmpl*RAND();				

	m_fLogoPos = -40 + fTime*10.0f;

	if( m_fAlpha < 0.0f )
		m_fAlpha = 0.0f;

	FLOAT					fXSize = BASEXSIZE + fTime*74.0f;
	FLOAT					fYSize = BASEYSIZE + fTime*37.0f;
			
	m_piqTitle->Resize( (512.0f - fXSize)*0.5f, (512.0f - fYSize)*0.5f, (512.0f + fXSize)*0.5f, (512.0f + fYSize)*0.5f );		

	if( fTime < 2.0f )
		return TRUE;

	fTime -= 2.0f;	

	FLOAT					fFlash;		

	m_fAngle = -fTime*1.0f;
	m_fSAlpha = (fTime - 3.0f)*0.5f;

	m_fCrackScale = 0.0f;
	m_fCrackAlpha = fTime - 1.0f;
	m_fCrackMove = fTime;

	if( m_fCrackAlpha < 0.0f )
		m_fCrackAlpha = 0.0f;
	else if( m_fCrackAlpha > 1.0f )
		m_fCrackAlpha = 1.0f;

	if( fTime > 1.0f )
		m_fCrackScale = 0.0f + (fTime-1.0f)*35.0f;	

	if( m_fSAlpha < 0.0f )
		m_fSAlpha = 0.0f;
	else if( m_fSAlpha > 1.0f )
		m_fSAlpha = 1.0f;

	if( fTime < 3.0f )
		fTime = 0.0f;
	else
		fTime -= 3.0f;	

	FLOAT fAlpha = ( fTime - (FLOAT)m_dwTextIndex )*255.0f;
	
	if( m_dwTextIndex < 3 )
	{
		if( fAlpha > 255.0f )
		{
			m_dwTextIndex++;
			fAlpha = 0.0f;
		}
	}
	else
	{
		if( fAlpha > 255.0f )
			fAlpha = 255.0f;
	}

	if( fTime > 1.5f && fTime < 2.5f )
	{
		m_bRenderFlash = TRUE;
		fFlash = 255.0f*sinf( (fTime - 1.5f)*H_PI );
		m_piqFlash->SetAlpha( (DWORD)fFlash );
		fFlash = 300.0f + 1200.0f*sinf( (fTime - 1.5f)*H_PI );
		m_piqFlash->Resize( 320.0f - 0.5f*fFlash, 240.0f - 0.5f*fFlash, 320.0f + 0.5f*fFlash, 240.0f + 0.5f*fFlash );
	}
	else if( fTime > 5.0f ) 
	{
		m_bRenderFade = TRUE;
		fFlash = 128.0f*( fTime - 5.0f );
		
		if( fFlash > 255.0f )
			fFlash = 255.0f;
		m_piqFlash->SetAlpha( (DWORD)fFlash );		

		m_piqFlash->Resize( 0.0f, 0.0f, 640.0f, 480.0f );
	}
	else
	{	
		m_bRenderFlash = FALSE;
		m_bRenderFade = FALSE;
	}

	m_piqTitle->SetAlpha( (DWORD)fAlpha );	
	
	if( fTime > 4.0f )
	{	
		m_mtxPiece[3] = TranslationMtx( -m_mPiece[3].GetCenter() )*RotationMtx( fTime-4.0f, 2.0f*fTime - 8.0f, -fTime + 4.0f )*TranslationMtx( m_mPiece[3].GetCenter() )*ScaleMtx( 1.42f, 1.07f, 1.0f )*TranslationMtx( 0, 0, 5 - 20.0f*(fTime - 4.0f) );
		m_bRenderVolume[3] = TRUE;
		m_fVolumeLen[3] = (fTime - 4.0f)*0.25f;
	}

	if( fTime > 3.5f )
	{	
		m_mtxPiece[4] = TranslationMtx( -m_mPiece[4].GetCenter() )*RotationMtx( -fTime+3.5f, fTime - 3.5f, -2.0f*fTime + 7.0f )*TranslationMtx( m_mPiece[4].GetCenter() )*ScaleMtx( 1.42f, 1.07f, 1.0f )*TranslationMtx( 0, 0, 5 - 20.0f*(fTime - 3.5f) );
		m_bRenderVolume[4] = TRUE;
		m_fVolumeLen[4] = (fTime - 3.5f)*0.25f;
	}

	if( fTime > 3.0f )
	{
		m_mtxPiece[1] = TranslationMtx( -m_mPiece[1].GetCenter() )*RotationMtx( fTime-3.0f, 2.0f*fTime - 6.0f, -2.0f*fTime + 6.0f )*TranslationMtx( m_mPiece[1].GetCenter() )*ScaleMtx( 1.42f, 1.07f, 1.0f )*TranslationMtx( 0, 0, 5 - 20.0f*(fTime - 3.0f) );
		m_bRenderVolume[1] = TRUE;
		m_fVolumeLen[1] = (fTime - 3.0f)*0.25f;
	}

	if( fTime > 2.5f )
	{
		m_mtxPiece[2] = TranslationMtx( -m_mPiece[2].GetCenter() )*RotationMtx( -2.0f*fTime + 5.0f, fTime + 2.5f, fTime - 2.5f )*TranslationMtx( m_mPiece[2].GetCenter() )*ScaleMtx( 1.42f, 1.07f, 1.0f )*TranslationMtx( 0, 0, 5 - 20.0f*(fTime - 2.5f) );
		m_bRenderVolume[2] = TRUE;
		m_fVolumeLen[2] = (fTime - 2.5f)*0.25f;
	}

	if( fTime > 2.0f )
	{	
		m_mtxPiece[0] = TranslationMtx( -m_mPiece[0].GetCenter() )*RotationMtx( 2.0f*fTime-4.0f, -2.0f*fTime + 4.0f, fTime - 2.0f )*TranslationMtx( m_mPiece[0].GetCenter() )*ScaleMtx( 1.42f, 1.07f, 1.0f )*TranslationMtx( 0, 0, 5 - 20.0f*(fTime - 2.0f) );
		m_bRenderVolume[0] = TRUE;
		m_fVolumeLen[0] = (fTime - 2.0f)*0.25f;
	}
					
	for( i = 0 ; i < 5 ; i++ )
		if( m_fVolumeLen[i] > 0.15f )
			m_fVolumeLen[i] = 0.15f;

	if( fTime > 2.0f )
	{		
		m_bRenderCrack = FALSE;

		if( fTime > 5.0f )
		{
			for( INT i = 0 ; i < 10 ; i++ )
				m_mtxMirror[i] = TranslationMtx( -m_mMirror[i].GetCenter() )*
								 ZRotationMtx( 2.0f*0.003f + (fTime - 5.0f)*0.1f )*
								 YRotationMtx( 2.0f*0.0025f )*
								 ScaleMtx( 1.0f + 0.02f*2.0f, 1.0f + 0.02f*2.0f, 1.0f )*
								 TranslationMtx( m_mMirror[i].GetCenter()*( 1.0f + (fTime-5.0f)*0.25f ) )*
								 TranslationMtx( 0, 0, -4.0f*fTime + 20.0f );
		}
		else
		{		
			for( INT i = 0 ; i < 10 ; i++ )
				m_mtxMirror[i] = TranslationMtx( -m_mMirror[i].GetCenter() )*
								 ZRotationMtx( 2.0f*0.003f )*
								 YRotationMtx( 2.0f*0.0025f )*
								 ScaleMtx( 1.0f + 0.02f*2.0f, 1.0f + 0.02f*2.0f, 1.0f )*
								 TranslationMtx( m_mMirror[i].GetCenter() );
		}
	}	

	return TRUE;
}

BOOL CTitleScreen::RenderEfx()
{	
	m_ptext->SetTarget( m_pDevice );

	m_pDevice->Clear( 0, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0x0, 1.0f, 0 );

	m_pDevice->SetTexture( 0, m_pptextMips[m_dwTextIndex] );
	m_pDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG1 );

	m_piqTitle->Render( m_pDevice );

	m_pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
	m_pDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA );
	m_pDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
	m_pDevice->SetTexture( 0, m_pptextMips[m_dwTextIndex+1] );
	m_pDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );

	m_piqTitle->Render( m_pDevice );
	
	m_pDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_SRCALPHA );
	m_pDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_INVSRCALPHA );

	m_pDevice->SetTexture( 0, m_pptextAlpha[m_dwAlphaIndex] );
	m_pDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_MODULATE );
	m_pDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_SELECTARG2 );

	m_piqTitle->SetAlpha( (DWORD)m_fAlpha );
	m_piqTitle->Render( m_pDevice );
		
	m_pDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
	m_pDevice->SetTextureStageState( 0, D3DTSS_COLOROP, D3DTOP_MODULATE );
	
	// logo

	m_pDevice->SetTexture( 0, GetTexture( "envmap4.jpg" ) );
	m_pDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );	
	m_pDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_CAMERASPACENORMAL );

	m_pDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_USEW );
	m_pDevice->SetRenderState( D3DRS_ZWRITEENABLE, TRUE );
	m_pDevice->SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );
	m_pDevice->SetRenderState( D3DRS_LIGHTING, FALSE );
	m_pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );		

	m_pDevice->SetTransform( D3DTS_TEXTURE0, RotationMtx( m_fAngle, 0.5f*m_fAngle, -m_fAngle )*TranslationMtx( 1.0f, 1.0f, 1.0f )*ScaleMtx( 0.5f ) );
	m_pDevice->SetTransform( D3DTS_WORLD, TranslationMtx( 0, 0, m_fLogoPos ) );	
	m_pmLogo->Render( m_pDevice );

	// s
	m_pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );		
	m_pDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
	m_pDevice->SetRenderState( D3DRS_AMBIENT, 0xffffff );
	m_pDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
	m_pDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );
	
	D3DMATERIAL8			d3dmat;
	ZeroMemory( &d3dmat, sizeof(D3DMATERIAL8) );
	
	d3dmat.Ambient.a = 1.0f;
	d3dmat.Ambient.r = 1.0f;
	d3dmat.Ambient.g = 1.0f;
	d3dmat.Ambient.b = 1.0f;
	d3dmat.Diffuse.a = m_fSAlpha*0.3f;
	
	m_pDevice->SetMaterial(  &d3dmat );
		
	m_pDevice->SetRenderState( D3DRS_ZWRITEENABLE, FALSE );

	m_pDevice->SetTexture( 0, GetTexture( "red.jpg" ) );
	
	m_pDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );
	m_pDevice->SetTransform( D3DTS_WORLD, ScaleMtx( 10.0f )*TranslationMtx( 0, 0, 400.0f ) );
	
	m_pmS->Render( m_pDevice );	

	m_pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );		
	m_pDevice->SetRenderState( D3DRS_LIGHTING, FALSE );	
	m_pDevice->SetTextureStageState( 0, D3DTSS_TEXCOORDINDEX, D3DTSS_TCI_PASSTHRU );
	m_pDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );
	m_pDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
	m_pDevice->SetRenderState( D3DRS_ZENABLE, D3DZB_FALSE );

	m_ptext->RestoreTarget( m_pDevice );	

	if( m_bRenderCrack )
		m_pDevice->Clear( 0, NULL, D3DCLEAR_TARGET, 0x0, 1.0f, 0 );	
	else
		m_pDevice->Clear( 0, NULL, D3DCLEAR_TARGET, 0xff0000, 1.0f, 0 );	

	m_pDevice->SetTexture( 0, m_ptext->GetTargetTexture() );	

	for( INT i = 0 ; i < 10 ; i++ )
	{	
		m_pDevice->SetTransform( D3DTS_WORLD, m_mtxMirror[i]*ScaleMtx( 1.42f, 1.07f, 1.0f )*TranslationMtx( 0, 0, 5 ) );		
		m_mMirror[i].Render( m_pDevice );		
	}	

	for( i = 0 ; i < 5 ; i++ )
	{
		m_pDevice->SetTransform( D3DTS_WORLD, m_mtxPiece[i] );
		m_mPiece[i].Render( m_pDevice );
	}

	m_pDevice->SetTexture( 0, GetTexture( "crack.jpg" ) );
	m_pDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );
	m_pDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2 );	

	m_pDevice->SetRenderState( D3DRS_LIGHTING, TRUE );
	m_pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, TRUE );
	m_pDevice->SetRenderState( D3DRS_DESTBLEND, D3DBLEND_ONE );
	m_pDevice->SetRenderState( D3DRS_SRCBLEND, D3DBLEND_SRCALPHA );

	ZeroMemory( &d3dmat, sizeof(D3DMATERIAL8) );

	d3dmat.Ambient.r = 1.0f;
	d3dmat.Ambient.g = 1.0f;
	d3dmat.Ambient.b = 1.0f;
	d3dmat.Diffuse.a = m_fCrackAlpha;
	d3dmat.Diffuse.r = 1.0f;
	d3dmat.Diffuse.g = 1.0f;
	d3dmat.Diffuse.b = 1.0f;
	
	m_pDevice->SetMaterial(  &d3dmat );
	
	m_pDevice->SetRenderState( D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL );

	m_pDevice->SetTransform( D3DTS_WORLD, ScaleMtx( 1.42f, 1.07f, m_fCrackScale )*TranslationMtx( 0, 0, 5 ) );	
	m_pDevice->SetTransform( D3DTS_TEXTURE0, YRotationMtx( 0.25f*m_fCrackMove ) );

	if( m_bRenderCrack )
	{	
		m_pDevice->SetVertexShader( FVF_LVERTEX );
		m_pDevice->SetStreamSource( 0, m_pvbCrack, sizeof(LVERTEX) );
		m_pDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, m_dwCrackFaces );
	}
	else
	{	
		m_pDevice->SetRenderState( D3DRS_LIGHTING, FALSE );			
		m_pDevice->SetTexture( 0, NULL );		

		for( i = 0 ; i < 5 ; i++ )
		{	
			if( !m_bRenderVolume[i] )
				continue;
			
			m_pDevice->SetTransform( D3DTS_WORLD, ScaleMtx( 1.42f, 1.07f, m_fVolumeLen[i] )*TranslationMtx( 0, 0, 5 ) );	
			m_pDevice->SetVertexShader( FVF_SIMPLEVERTEX );
			m_pDevice->SetStreamSource( 0, m_pvbVolumetic[i], sizeof(SIMPLEVERTEX) );
			m_pDevice->DrawPrimitive( D3DPT_TRIANGLELIST, 0, m_dwVolumeFaces[i] );
			m_pDevice->SetStreamSource( 0, m_pvbInnerVolumetric[i], sizeof(SIMPLEVERTEX) );
			m_pDevice->SetIndices( m_pibInnerVolumetric[i], 0 );
			m_pDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, 0, 50*m_mPiece[i].GetVertexCount(), 0, 50*m_mPiece[i].GetFacesCount() );
		}
	}

	m_pDevice->SetRenderState( D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1 );

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

	if( m_bRenderFlash )
	{
		m_pDevice->SetTexture( 0, GetTexture( "flash.jpg" ) );
		m_piqFlash->Render( m_pDevice );
	}	

	if( m_bRenderFade )
	{
		m_pDevice->SetTexture( 0, NULL );
		m_piqFlash->Render( m_pDevice );
	}
		
	m_pDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
	m_pDevice->SetTextureStageState( 0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE );	

	m_pDevice->SetRenderState( D3DRS_ALPHABLENDENABLE, FALSE );

	return TRUE;
}
