//----------------------------------------------------------------------------------------------
// weird cube efect, oh yeah i love that !
// by (guess who) yup ol' acid from z51 :)
//----------------------------------------------------------------------------------------------
// this file is part of source code from intertia³ demo (c)zone51 `2000
//----------------------------------------------------------------------------------------------

#define	 D3D_OVERLOADS
#include "nCubeEfx.h"
#include "gemmath.h"
#include "extrastuff.h"
#include "texture.h"
#include "texturemenager.h"

#define	 LIGHTNBR		60

// here we go with some globals
static	D3DLVERTEX				Flare[4];

static	D3DVERTEX				cubes[36*125];
static	D3DLVERTEX				lcubes[24*125];

static	D3DVERTEX				BigCube[36];

static	D3DLIGHT7				light;

static	gem_Vector				Path[LIGHTNBR][30];
static	D3DLVERTEX				Line[LIGHTNBR][30];
static	WORD					LinePos = 1;

static	D3DTLVERTEX				FadeV[4];
static	DWORD					Fade = 0;

static  gem_Matrix				invCam;
static	gem_Vector				t, p;

static	gem_Vector				t1, t2, t3;
static	D3DLIGHT7				lit1, lit2, lit3;

static	D3DTLVERTEX				Overground[4];

static	LPDIRECTDRAWSURFACE7	mask = NULL;
static	D3DTLVERTEX				maskFace[4];
static	DWORD					renderMask = 0;

static	DWORD					renderMini = 0;
static	DWORD					renderRB = 1;

static	FLOAT					xr, yr;
static	FLOAT					ysizer, xsizer;
static	FLOAT					xsizeB, ysizeB;

static	D3DVIEWPORT7			view;

static	FLOAT					vpx, vpy;	// viewportsizes

static	D3DMATRIX				miniCam;
static  gem_Matrix				invCamMini;

static	DWORD					text;
static	FLOAT					posx;
static	DWORD					text_alpha;

#define RND() (((FLOAT)rand())/RAND_MAX)

VOID GeneratePath( gem_Vector* path, long x, long y, long z, DWORD pathlen = 30 )
{
	path[0].x = (FLOAT)x*3.0f - 4.5f;
	path[0].y = (FLOAT)y*3.0f - 4.5f;
	path[0].z = (FLOAT)z*3.0f - 4.5f;
	
	long	lastx = x, lasty = y, lastz = z;
	long	oldx, oldy, oldz;
	long	newx, newy, newz;
	DWORD	pathpos = 0;

	while( ++pathpos < pathlen )
	{
		while( 1 )
		{
			DWORD	dir = RND()*5.0f;

			newx = lastx; newy = lasty; newz = lastz;

			switch( dir )
			{
				case 0: newx += 1; break;
				case 1: newx -= 1; break;
				case 2: newz -= 1; break;
				case 3: newy += 1; break;
				case 4: newy -= 1; break;
				case 5: newz += 1; break;
			}

			if( newx<-1 || newx>4 || newy<-1 || newy>4 || newz<-1 || newz>4 )
				continue;

			if( newx == oldx && newy == oldy && newz == oldz )
				continue;

			break;
		}
		
		path[pathpos].x = (FLOAT)newx*3.0f - 4.5f;
		path[pathpos].y = (FLOAT)newy*3.0f - 4.5f;
		path[pathpos].z = (FLOAT)newz*3.0f - 4.5f;

		oldx = lastx; oldy = lasty; oldz = lastz;
		lastx = newx; lasty = newy; lastz = newz;
	}		
}

// read some textures and do some stuff
HRESULT fxInit_nCubeEfx( LPDIRECT3DDEVICE7 pd3dDevice )
{
	LoadAlphaChannel( "data\\textures\\move.bmp", &mask, pd3dDevice );

	LoadTexture( "data\\textures\\cubex.jpg", pd3dDevice );	
	LoadTexture( "data\\textures\\light2.jpg", pd3dDevice );	
	LoadTexture( "data\\textures\\ramka.jpg", pd3dDevice );		 
	LoadTexture( "data\\texts\\napis_4.jpg", pd3dDevice );

	LoadTexture( "data\\textures\\fg_nCubex.jpg", pd3dDevice );	
	LPDIRECTDRAWSURFACE7	surf = GetTexture( "data\\textures\\fg_nCubex.jpg" );
	LoadAlphaChannel( "data\\textures\\fg_nCubex_alpha.bmp", &surf, pd3dDevice, 0 );	

	LPD3DVERTEX		_ncube  = cubes;
	LPD3DLVERTEX	_nlcube = lcubes;

	for( int i = 0 ; i<5 ; i++ )
		for( int j = 0 ; j<5 ; j++ )
			for( int k = 0 ; k<5 ; k++, _ncube += 36, _nlcube += 24 )
			{
				CreateCube( _ncube,  1.0f, gem_Vector( (FLOAT)i*3.0f - 6.0f, (FLOAT)j*3.0f - 6.0f, (FLOAT)k*3.0f - 6.0f ) );
				CreateLCube( _nlcube, 1.1f, gem_Vector( (FLOAT)i*3.0f - 6.0f, (FLOAT)j*3.0f - 6.0f, (FLOAT)k*3.0f - 6.0f ) );
			}				

	CreateCube( BigCube, 15.0f );

	DWORD sx = 0, sy = 0, sz = 0;

	for( int j = 0 ; j < LIGHTNBR ; j++ )
	{
		for( int i = 0 ; i < 30 ; i++ )
			Line[j][i] = D3DLVERTEX( D3DVECTOR( 0, 0, 0 ), 0x40ffffff, 0, 0, 0 );

		GeneratePath( Path[j], sx%4, sy%4, sz%4 );

		sx = sx + 2; sy = sy + 1; sz = sz + 3;
	}

	Flare[0] = D3DLVERTEX( D3DVECTOR(-0.25, 0.25, 0 ), 0x80ffffff, 0, 0, 0 );
	Flare[1] = D3DLVERTEX( D3DVECTOR( 0.25, 0.25, 0 ), 0x80ffffff, 0, 1, 0 );
	Flare[2] = D3DLVERTEX( D3DVECTOR(-0.25,-0.25, 0 ), 0x80ffffff, 0, 0, 1 );
	Flare[3] = D3DLVERTEX( D3DVECTOR( 0.25,-0.25, 0 ), 0x80ffffff, 0, 1, 1 );			

	t1 = gem_Vector( 0, 0, 1 );
	t2 = gem_Vector( -0.86f, 0, -0.5f );
	t3 = gem_Vector( 0.86f, 0, -0.5f );

	ZeroMemory( &light, sizeof(light) );
	lit1.dltType		= D3DLIGHT_SPOT;
	lit1.dcvDiffuse.r	= 1.0f;
	lit1.dcvDiffuse.g	= 0.0f;
	lit1.dcvDiffuse.b	= 0.0f;	
	lit1.dvAttenuation0 = 1.0f;
	lit1.dvAttenuation1 = 0.02f;
	lit1.dvAttenuation2 = 0;
	lit1.dvRange		= 40.0f;
	lit1.dvTheta		= 0.15*3.14159;
	lit1.dvPhi			= 0.3*3.14159;
	lit1.dvFalloff		= .2f;

	lit2.dltType		= D3DLIGHT_SPOT;
	lit2.dcvDiffuse.r	= 0.0f;
	lit2.dcvDiffuse.g	= 0.0f;
	lit2.dcvDiffuse.b	= 1.0f;	
	lit2.dvAttenuation0 = 1.0f;
	lit2.dvAttenuation1 = 0.02f;
	lit2.dvAttenuation2 = 0;
	lit2.dvRange		= 40.0f;
	lit2.dvTheta		= 0.15*3.14159;
	lit2.dvPhi			= 0.3*3.14159;
	lit2.dvFalloff		= .2f;

	lit3.dltType		= D3DLIGHT_SPOT;
	lit3.dcvDiffuse.r	= 0.0f;
	lit3.dcvDiffuse.g	= 1.0f;
	lit3.dcvDiffuse.b	= 0.0f;	
	lit3.dvAttenuation0 = 1.0f;
	lit3.dvAttenuation1 = 0.02f;
	lit3.dvAttenuation2 = 0;
	lit3.dvRange		= 40.0f;
	lit3.dvTheta		= 0.15*3.14159;
	lit3.dvPhi			= 0.3*3.14159;
	lit3.dvFalloff		= .2f;

	D3DVECTOR vFar = D3DVECTOR( 0.0f, 0.0f, 0.5f );
    FadeV[0] = D3DTLVERTEX( vFar, 0.5f, 0xFFFFFFFF, 0, 0.01f, 0.99f );
    FadeV[1] = D3DTLVERTEX( vFar, 0.5f, 0xFFFFFFFF, 0, 0.01f, 0.01f );
    FadeV[2] = D3DTLVERTEX( vFar, 0.5f, 0xFFFFFFFF, 0, 0.99f, 0.99f );
    FadeV[3] = D3DTLVERTEX( vFar, 0.5f, 0xFFFFFFFF, 0, 0.99f, 0.01f );	

	maskFace[0] = D3DTLVERTEX( vFar, 0.5f, 0, 0, 0.01f, 0.99f );
    maskFace[1] = D3DTLVERTEX( vFar, 0.5f, 0, 0, 0.01f, 0.01f );
    maskFace[2] = D3DTLVERTEX( vFar, 0.5f, 0, 0, 0.99f, 0.99f );
    maskFace[3] = D3DTLVERTEX( vFar, 0.5f, 0, 0, 0.99f, 0.01f );	

	Overground[0] = D3DTLVERTEX( vFar, 0.5f, 0xFFFFFFFF, 0, 0.01f, 0.99f );
    Overground[1] = D3DTLVERTEX( vFar, 0.5f, 0xFFFFFFFF, 0, 0.01f, 0.01f );
    Overground[2] = D3DTLVERTEX( vFar, 0.5f, 0xFFFFFFFF, 0, 0.99f, 0.99f );
    Overground[3] = D3DTLVERTEX( vFar, 0.5f, 0xFFFFFFFF, 0, 0.99f, 0.01f );	

	D3DVIEWPORT7 vp;
    pd3dDevice->GetViewport(&vp);
    FadeV[0].sy = (FLOAT)vp.dwHeight;
    FadeV[2].sy = (FLOAT)vp.dwHeight;
    FadeV[2].sx = (FLOAT)vp.dwWidth;
    FadeV[3].sx = (FLOAT)vp.dwWidth;	    
	    
    Overground[0].sy = (FLOAT)vp.dwHeight;
    Overground[2].sy = (FLOAT)vp.dwHeight;
    Overground[2].sx = (FLOAT)vp.dwWidth;
    Overground[3].sx = (FLOAT)vp.dwWidth;		

	view.dwWidth	= vp.dwWidth*0.3f;
	view.dwHeight	= vp.dwHeight*0.3f;
	view.dwX		= vp.dwWidth - vp.dwWidth*0.4f;
	view.dwY		= vp.dwHeight - vp.dwHeight*0.4f;
    view.dvMaxZ     = 1.0f;
	view.dvMinZ		= 0.0f;

	vpx = vp.dwWidth;
	vpy = vp.dwHeight;	
	
	return S_OK;
}

HRESULT fxFrameMove_nCubeEfx( LPDIRECT3DDEVICE7 pd3dDevice, LPSYNCINFO sync )
{

	FLOAT		fTimeKey = sync->fTimeKey;

	DWORD		color = (DWORD)((3 + sin( fTimeKey*2 ))*30.0f);
	color = (color << 24)|0xffffff;

	SetColorValue( lcubes, 24*125, color );

	//********************************************************************
	

	D3DMATERIAL7       mtrl;
	ZeroMemory( &mtrl, sizeof(mtrl) );
    mtrl.dcvAmbient.r = 0.4f;
    mtrl.dcvAmbient.g = 0.4f;
    mtrl.dcvAmbient.b = 0.4f;
	mtrl.dcvDiffuse.r = 1.0f;
    mtrl.dcvDiffuse.g = 1.0f;
    mtrl.dcvDiffuse.b = 1.0f;
	mtrl.dcvDiffuse.a = 0.25f;
    pd3dDevice->SetMaterial( &mtrl );

	D3DMATRIX mat;
	mat._11 = mat._22 = mat._33 = mat._44 = 1.0f;
	mat._12 = mat._13 = mat._14 = mat._41 = 0.0f;
	mat._21 = mat._23 = mat._24 = mat._42 = 0.0f;
	mat._31 = mat._32 = mat._34 = mat._43 = 0.0f;

	D3DMATRIX matWorld = mat;
    pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &matWorld );	

	// The projection matrix defines how the 3D scene is "projected" onto the
	// 2D render target (the backbuffer surface). Refer to the docs for more
	// info about projection matrices.
	D3DMATRIX matProj = (D3DMATRIX)ProjectionMtx( 40.0f, 0.5f, 1000.0f, 0.70f );
	pd3dDevice->SetTransform( D3DTRANSFORMSTATE_PROJECTION, &matProj );

	pd3dDevice->SetRenderState( D3DRENDERSTATE_AMBIENT, 0xFFFFFFFF );

	//*********************************************************************	
	
	D3DMATRIX	matView;

	if( fTimeKey<7 )
	{
		t = gem_Vector(  5.5f,  5.5f, -4.5f );
		p = gem_Vector( -12.5f, -12.5f, -4.5f );

		t = t*TranslationMtx( 2.5*fTimeKey*gem_Vector( 1, 1, 0 ) );
		p = p*TranslationMtx( 2.5*fTimeKey*gem_Vector( 1, 1, 0 ) );		
	}

	
	if( fTimeKey<10.5 && fTimeKey>=7 )
	{
		t = gem_Vector(  -1.5f,  1.5f,  10.0f );
		p = gem_Vector(  -1.5f,  1.5f, -12.0f );

		t = t*TranslationMtx( 5.0f*(fTimeKey-7.0f)*gem_Vector( 0, 0, 1 ) );
		p = p*TranslationMtx( 5.0f*(fTimeKey-7.0f)*gem_Vector( 0, 0, 1 ) );		
	}

	if( fTimeKey<20.5 && fTimeKey>=10.5 )
	{
		t = gem_Vector(  0.0f,  0.0f,  0.0f );
		p = gem_Vector(  0.0f,  0.0f, 14.0f );

		p = p*RotationMtx( fTimeKey*0.25f, fTimeKey*0.35f, -fTimeKey*0.15f );		
	}

	if( fTimeKey<26.0f && fTimeKey>=20.5 )
	{
		t = gem_Vector(  -1.5f,  10.0f,  0.0f );
		p = gem_Vector(  -1.5f,  -12.5f,  0.0f );

		t = t*TranslationMtx( 3.0f*(fTimeKey-20.5f)*gem_Vector( 0, 1, 0 ) );
		p = p*TranslationMtx( 3.0f*(fTimeKey-20.5f)*gem_Vector( 0, 1, 0 ) );		
	}

	if( fTimeKey<31.0f && fTimeKey>=26.0f )
	{
		t = gem_Vector(   6.0f,  1.5f,   6.0f );
		p = gem_Vector(   -12.5f,  1.5f,  -12.5f );

		t = t*TranslationMtx( 4*(fTimeKey-26.0f)*gem_Vector( 1, 0, 1 ) );
		p = p*TranslationMtx( 4*(fTimeKey-26.0f)*gem_Vector( 1, 0, 1 ) );		
	}

	if( fTimeKey > 31.0f )
	{
		t = gem_Vector(  5.5f,  5.5f, 1.5f );
		p = gem_Vector( -12.5f, -12.5f, 1.5f );

		t = t*TranslationMtx( 4*(fTimeKey-31.0f)*gem_Vector( 1, 1, 0 ) );
		p = p*TranslationMtx( 4*(fTimeKey-31.0f)*gem_Vector( 1, 1, 0 ) );		
	}

	matView = (D3DMATRIX)CameraMtx( p, t, 0 );	

	pd3dDevice->SetTransform( D3DTRANSFORMSTATE_VIEW, &matView );

	invCam = InvCameraMtx( p, t, 0 );

	t = gem_Vector(  0.0f,  0.0f,  0.0f );
	p = gem_Vector(  0.0f,  0.0f, 14.0f );

	p = p*RotationMtx( fTimeKey*0.35f, -fTimeKey*0.15f, -fTimeKey*0.25f );		

	miniCam = (D3DMATRIX)CameraMtx( p, t, fTimeKey*0.25f );
	invCamMini = InvCameraMtx( p, t, fTimeKey*0.25f );

	Fade = 0;
	DWORD	alpha;

	if( fTimeKey < 1.0f )
	{
		Fade = 1;

		alpha = (DWORD)( ( 1.0f - fTimeKey )*255.0f );
	}

	if( fTimeKey < 8.0f && fTimeKey > 7.0f )
	{
		Fade = 1;

		alpha = (DWORD)( ( 8.0f - fTimeKey )*255.0f );
	}

	if( fTimeKey < 11.5f && fTimeKey > 10.5f )
	{
		Fade = 1;

		alpha = (DWORD)( ( 11.5f - fTimeKey )*255.0f );
	}

	if( fTimeKey < 21.5f && fTimeKey > 20.5f )
	{
		Fade = 1;

		alpha = (DWORD)( ( 21.5f - fTimeKey )*255.0f );
	}

	if( fTimeKey < 27.0f && fTimeKey > 26.0f )
	{
		Fade = 1;

		alpha = (DWORD)( ( 27.0f - fTimeKey )*255.0f );
	}

	if( fTimeKey < 32.0f && fTimeKey > 31.0f )
	{
		Fade = 1;

		alpha = (DWORD)( ( 32.0f - fTimeKey )*255.0f );
	}

	if( alpha > 255 ) 
		alpha = 255;

	alpha <<= 24;

	FadeV[0].dcColor = alpha | 0xffffff;
	FadeV[1].dcColor = alpha | 0xffffff;
	FadeV[2].dcColor = alpha | 0xffffff;
	FadeV[3].dcColor = alpha | 0xffffff;	

	lit1.dvPosition.x	= p.x;
	lit1.dvPosition.y	= p.y;
	lit1.dvPosition.z	= p.z;

	lit2.dvPosition.x	= p.x;
	lit2.dvPosition.y	= p.y;
	lit2.dvPosition.z	= p.z;

	lit3.dvPosition.x	= p.x;
	lit3.dvPosition.y	= p.y;
	lit3.dvPosition.z	= p.z;

	gem_Vector			dir1, dir2, dir3;
	gem_Matrix			mtx = RotationMtx( 2.5*fTimeKey, -1.5*fTimeKey, 2*fTimeKey );

	dir1 = Normalize( t1*mtx );
	dir2 = Normalize( t2*mtx );
	dir3 = Normalize( t3*mtx );

	lit1.dvDirection.x = dir1.x;
	lit1.dvDirection.y = dir1.y;
	lit1.dvDirection.z = dir1.z;

	lit2.dvDirection.x = dir2.x;
	lit2.dvDirection.y = dir2.y;
	lit2.dvDirection.z = dir2.z;

	lit3.dvDirection.x = dir3.x;
	lit3.dvDirection.y = dir3.y;
	lit3.dvDirection.z = dir3.z;

	pd3dDevice->SetLight( 0, &lit1 );		
	pd3dDevice->SetLight( 1, &lit2 );		
	pd3dDevice->SetLight( 2, &lit3 );			

	FLOAT		locTime;

	for( int i = 0 ; i<30 ; i++ )
	{
		for( int j = 0 ; j < LIGHTNBR ; j++ )
		{
			Line[j][i].x = Path[j][i].x;
			Line[j][i].y = Path[j][i].y;
			Line[j][i].z = Path[j][i].z;
		}

		if( (FLOAT)(i+1) > fTimeKey && (FLOAT)i < fTimeKey )
		{
			LinePos = i+1;
			locTime = fTimeKey - (FLOAT)i;
			break;
		}
	}

	if( LinePos > 30 )
	{
		LinePos  = 30;
	}
	else
	{
		for( int i = 0 ; i < LIGHTNBR ; i++ )
		{
			Line[i][LinePos].x = Path[i][LinePos-1].x + (Path[i][LinePos].x - Path[i][LinePos-1].x)*locTime;
			Line[i][LinePos].y = Path[i][LinePos-1].y + (Path[i][LinePos].y - Path[i][LinePos-1].y)*locTime;
			Line[i][LinePos].z = Path[i][LinePos-1].z + (Path[i][LinePos].z - Path[i][LinePos-1].z)*locTime;
		}
		
	}	

	if( fTimeKey < 2.0f )
	{
		renderMini = 0;		

		xr = view.dwX + view.dwWidth*0.5f;
		yr = view.dwY + view.dwHeight*0.5f;

		xsizer = 220 - 100.0f*fTimeKey + view.dwWidth;
		ysizer = 170 - 75.0f*fTimeKey + view.dwHeight;		
	}
	else
	{
		renderMini = 1;		

		xr = view.dwX + view.dwWidth*0.5f;
		yr = view.dwY + view.dwHeight*0.5f;

		xsizer = 20 + view.dwWidth;
		ysizer = 20 + view.dwHeight;
	}		

	if( fTimeKey < 4.0f )
	{
		renderRB = 1;

		xsizeB = 220 - 100.0f*fTimeKey + view.dwWidth;
		ysizeB = 170 - 75.0f*fTimeKey + view.dwHeight;		
	}
	else
		renderRB = 0;

	if( fTimeKey > 34.0f )
	{
		renderMask = 1;

		maskFace[0].sx = ((vpx + 600))*((fTimeKey-34.0f)*0.333f -1.0f);
		maskFace[0].sy = vpy;

		maskFace[1].sx = ((vpx + 600))*((fTimeKey-34.0f)*0.333f -1.0f);
		maskFace[1].sy = 0;

		maskFace[2].sx = ((vpx + 600))*(fTimeKey-34.0f)*0.333f;
		maskFace[2].sy = vpy;

		maskFace[3].sx = ((vpx + 600))*(fTimeKey-34.0f)*0.333f;
		maskFace[3].sy = 0;		
	}	

	if( fTimeKey > 13.0f && fTimeKey < 18.0f )
	{
		text = 1;
		text_alpha = (DWORD)(sinf( (fTimeKey - 13.0f)*3.1415f*0.2f )*200.0f);
		posx = 200 + (fTimeKey-13.0f)*20.0f;
	}

	return S_OK;
}

HRESULT fxRender_nCubeEfx( LPDIRECT3DDEVICE7 pd3dDevice )
{		
	D3DMATRIX				mat = IdentMtx();

	D3DVIEWPORT7			old;	
	D3DRECT					rect;
	DWORD					i;

	pd3dDevice->GetViewport( &old );		

	pd3dDevice->Clear( 1UL, NULL, D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL , 0x00000000, 1.0f, 0L );			
	
	pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &mat );

	pd3dDevice->LightEnable( 0, TRUE );
	pd3dDevice->LightEnable( 1, TRUE );
	pd3dDevice->LightEnable( 2, TRUE );

	pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTFN_LINEAR );	
	pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTFG_LINEAR );
	pd3dDevice->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTFN_ANISOTROPIC );	
	pd3dDevice->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTFG_ANISOTROPIC );
	pd3dDevice->SetTextureStageState( 0, D3DTSS_MAXANISOTROPY, 2 );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_STENCILENABLE, FALSE );

	pd3dDevice->SetRenderState( D3DRENDERSTATE_WRAP0, FALSE ); 	
	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ZENABLE, D3DZB_USEW );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, TRUE );

	pd3dDevice->BeginScene();

	pd3dDevice->SetTexture( 0, GetTexture( "data\\textures\\cubex.jpg" ) );	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, FALSE );	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_CCW );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, TRUE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD );  
	pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, D3DFVF_VERTEX, cubes, 36*125, NULL );	

	pd3dDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_CW );

	pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, D3DFVF_VERTEX, BigCube, 36, NULL );	

	pd3dDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, FALSE );

	pd3dDevice->SetTexture( 0, GetTexture( "data\\textures\\light2.jpg" ) );	

	pd3dDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_NONE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, TRUE );	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE );

	D3DMATRIX	lightMat;

	pd3dDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, FALSE );

	for( i = 0 ; i<LIGHTNBR ; i++ )
	{
		lightMat = (D3DMATRIX)(invCam*TranslationMtx( Line[i][LinePos].x, Line[i][LinePos].y, Line[i][LinePos].z ));
		pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &lightMat );

		pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, Flare, 4, NULL );
	}

	pd3dDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, TRUE );
		
	pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &mat );

	pd3dDevice->SetTexture( 0, NULL );	

	pd3dDevice->SetRenderState( D3DRENDERSTATE_ANTIALIAS, D3DANTIALIAS_SORTINDEPENDENT );

	pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, TRUE );	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE );
	
	pd3dDevice->DrawPrimitive( D3DPT_LINELIST, D3DFVF_LVERTEX, lcubes, 24*125, NULL );	

	/*
	for( i = 0 ; i<LIGHTNBR ; i++ )
	{
		pd3dDevice->DrawPrimitive( D3DPT_LINESTRIP, D3DFVF_LVERTEX, Line[i], LinePos+1, NULL );	
	}*/

	pd3dDevice->SetRenderState( D3DRENDERSTATE_ZENABLE, D3DZB_FALSE );	

	pd3dDevice->SetRenderState( D3DRENDERSTATE_ANTIALIAS, FALSE );

	pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, TRUE );	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND, D3DBLEND_INVSRCALPHA );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_SRCALPHA );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, FALSE );	

	pd3dDevice->SetTexture( 0, GetTexture( "data\\textures\\fg_nCubex.jpg" ) );	
	pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, D3DFVF_TLVERTEX, Overground, 4, 0 );

	pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, TRUE );	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE );	

	if( renderRB )
	{
		FLOAT	SX, SY;

		for( int i = 0 ; i < 10 ; i++ )
		{
			SX = xsizeB + (i+1)*10;
			SY = ysizeB + (i+1)*10;

			if( SX < view.dwWidth + 20 )
				SX = view.dwWidth + 20;

			if( SY < view.dwHeight + 20 )
				SY = view.dwHeight + 20;

			RenderEfxFace( xr, yr, SX, SY, 20, GetTexture( "data\\textures\\ramka.jpg" ), pd3dDevice );
		}
	}

	RenderEfxFace( xr, yr, xsizer, ysizer, 255, GetTexture( "data\\textures\\ramka.jpg" ), pd3dDevice );

	if( renderMini )
	{
		pd3dDevice->SetViewport( &view );
		pd3dDevice->Clear( 1UL, NULL, D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0L );		

		//*************************

		pd3dDevice->SetRenderState( D3DRENDERSTATE_ZENABLE, D3DZB_USEW );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, TRUE );
		pd3dDevice->SetTransform( D3DTRANSFORMSTATE_VIEW, &miniCam );

		pd3dDevice->SetTexture( 0, GetTexture( "data\\textures\\cubex.jpg" ) );	
		pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, FALSE );	
		pd3dDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_CCW );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, TRUE );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_SHADEMODE, D3DSHADE_GOURAUD );  
		pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, D3DFVF_VERTEX, cubes, 36*125, NULL );	

		pd3dDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_CW );

		pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, D3DFVF_VERTEX, BigCube, 36, NULL );	

		pd3dDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, FALSE );

		pd3dDevice->SetTexture( 0, GetTexture( "data\\textures\\light2.jpg" ) );	

		pd3dDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_NONE );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, TRUE );	
		pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE );	

		pd3dDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, FALSE );

		for( i = 0 ; i<LIGHTNBR ; i++ )
		{
			lightMat = (D3DMATRIX)(invCamMini*TranslationMtx( Line[i][LinePos].x, Line[i][LinePos].y, Line[i][LinePos].z ));
			pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &lightMat );

			pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, Flare, 4, NULL );
		}

		pd3dDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, TRUE );
			
		pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &mat );

		pd3dDevice->SetTexture( 0, NULL );	

		pd3dDevice->SetRenderState( D3DRENDERSTATE_ANTIALIAS, D3DANTIALIAS_SORTINDEPENDENT );

		pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, TRUE );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE );
		
		pd3dDevice->DrawPrimitive( D3DPT_LINELIST, D3DFVF_LVERTEX, lcubes, 24*125, NULL );	

		/*for( i = 0 ; i<LIGHTNBR ; i++ )
		{
			pd3dDevice->DrawPrimitive( D3DPT_LINESTRIP, D3DFVF_LVERTEX, Line[i], LinePos+1, NULL );	
		}*/	

		pd3dDevice->SetRenderState( D3DRENDERSTATE_ANTIALIAS, FALSE );	

		pd3dDevice->SetViewport( &old );
	}

	//*********************************************

	pd3dDevice->SetRenderState( D3DRENDERSTATE_ZENABLE, D3DZB_FALSE );		

	if( text )
		RenderEfxFace( posx, 80, 369, 95, text_alpha, GetTexture( "data\\texts\\napis_4.jpg" ), pd3dDevice );
	
	if( Fade )
	{		
		pd3dDevice->SetTexture( 0, NULL );
		pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, D3DFVF_TLVERTEX, FadeV, 4, 0 );				
	}			
	
	if( renderMask )
	{				
		pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, TRUE );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA );		
		//pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );		

		pd3dDevice->SetTexture( 0, mask );

		pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, D3DFVF_TLVERTEX, maskFace, 4, 0 );

		// mask the part of the next scene witch stencil

		pd3dDevice->SetRenderState( D3DRENDERSTATE_STENCILENABLE, TRUE );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_STENCILFUNC,   D3DCMP_ALWAYS );

		pd3dDevice->SetRenderState( D3DRENDERSTATE_STENCILZFAIL, D3DSTENCILOP_REPLACE );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_STENCILFAIL,  D3DSTENCILOP_REPLACE );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_STENCILPASS,  D3DSTENCILOP_REPLACE );

		pd3dDevice->SetRenderState( D3DRENDERSTATE_STENCILREF,      0x1 );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_STENCILMASK,     0xffffffff );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_STENCILWRITEMASK,0xffffffff );

		maskFace[0].sx -= 300;
		maskFace[1].sx -= 300;
		maskFace[2].sx -= 300;
		maskFace[3].sx -= 300;

		pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND, D3DBLEND_ZERO );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE );

		pd3dDevice->SetTexture( 0, NULL );

		pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, D3DFVF_TLVERTEX, maskFace, 4, 0 );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_STENCILENABLE, FALSE );
	}	

	pd3dDevice->SetTexture( 0, NULL );
		
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ZENABLE, D3DZB_USEW );

	pd3dDevice->LightEnable( 0, FALSE );
	pd3dDevice->LightEnable( 1, FALSE );
	pd3dDevice->LightEnable( 2, FALSE );	

	pd3dDevice->EndScene();

	return S_OK;
}

#define SAFE_RELEASE( obj ) \
	 if( obj ) obj->Release()

VOID fxDelete_nCubeEfx( LPDIRECT3DDEVICE7 pd3dDevice )
{		
	SAFE_RELEASE( mask );
}
