//----------------------------------------------------------------------------------------------
// oh yeah blobs with mirrors that kick azz 
// could it be acid/z51 code?, yup indeed :)
//----------------------------------------------------------------------------------------------
// this file is part of source code from inertia³ demo (c)zone51 `2000
//----------------------------------------------------------------------------------------------

#define	 D3D_OVERLOADS
#include "BlobsMirrorEfx.h"
#include "blobs.h"
#include "texture.h"
#include "extrastuff.h"
#include "texturemenager.h"

// lots of globals

static	D3DMATRIX				g_matLocal;
static	D3DMATRIX				matBackLocal[10];
static	D3DMATRIX				matBannerLocal[10];

static	D3DLVERTEX				MirrorVerts[4][4];
static	D3DLVERTEX				ClipVerts[4][4];

static	D3DLVERTEX				Banner[4];

static	D3DLVERTEX				MirrorPlain[4][4];
static	D3DLVERTEX				ClipPlain[4][4];

static	D3DTLVERTEX				Background[4];           // Vertices used to render the backdrop
static	D3DTLVERTEX				Overground[4];
static	D3DTLVERTEX				LightBarVer[4];
static	D3DTLVERTEX				LightBarHrz[4];

static	D3DLVERTEX				Plain[4];

static	LPDIRECTDRAWSURFACE7	mask		= NULL;

static	BLOBGRID				g_Grid;
static	BLOB3D					boob[10];

static	D3DVERTEX				vertab1[20000];
static	D3DVERTEX				vertab2[20000];

static	FLOAT					lbVerPos[10];
static	FLOAT					lbHrzPos[10];

static	gem_Vector				pos[5];
static	FLOAT					alpha;

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

static	DWORD					text1 = 0;
static	DWORD					text1_alpha;
static	FLOAT					sizey;
static	DWORD					stretch = 0;
static	DWORD					blur = 0;
static	FLOAT					b_sizex[5];
static	FLOAT					b_alpha[5];

static	DWORD					text2 = 0;
static	FLOAT					tx2size;
static	DWORD					text2_alpha;

FLOAT* CreatePlane( FLOAT* plane, gem_Vector& a, gem_Vector& b, gem_Vector& c )
{
    gem_Vector	n = Normalize( Cross( b-c, a-c ) );

    plane[0] = n.x; 
	plane[1] = n.y; 
	plane[2] = n.z; 
    plane[3] = -( n.x*c.x + n.y*c.y + n.z*c.z );

    return plane;
}

VOID MirrorMtx( D3DMATRIX& matMirror, gem_Vector& n, FLOAT D )
{
	matMirror = (D3DMATRIX)IdentMtx();

    matMirror._11 -= 2*n.x*n.x; matMirror._12 -= 2*n.x*n.y; matMirror._13 -= 2*n.x*n.z;
    matMirror._21 -= 2*n.y*n.x; matMirror._22 -= 2*n.y*n.y; matMirror._23 -= 2*n.y*n.z;
    matMirror._31 -= 2*n.z*n.x; matMirror._32 -= 2*n.z*n.y; matMirror._33 -= 2*n.z*n.z;
    matMirror._41 -= 2*D*n.x;   matMirror._42 -= 2*D*n.y;   matMirror._43 -= 2*D*n.z;	
}

// just some initialization, ya know tekstures blobz etc
HRESULT fxInit_Blobs( LPDIRECT3DDEVICE7 pd3dDevice )
{	
	LoadTexture( "data\\textures\\nopee1.jpg", pd3dDevice );		
	LoadTexture( "data\\textures\\env.jpg", pd3dDevice );
	LoadTexture( "data\\textures\\blobo.jpg", pd3dDevice );	
	LoadTexture( "data\\textures\\ramka.bmp", pd3dDevice );	
	LoadTexture( "data\\textures\\tyl.bmp", pd3dDevice );	
	LoadTexture( "data\\textures\\efxx.jpg", pd3dDevice );		
	LoadTexture( "data\\texts\\napis_1.jpg", pd3dDevice );
	LoadTexture( "data\\texts\\napis_10.jpg", pd3dDevice );
	
	LoadAlphaChannel( "data\\textures\\baran1.bmp", &mask, pd3dDevice );			

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

	D3DVECTOR	GridPos(0,0,0);	

	pos[0] = gem_Vector( -2.5, 0, 0);
	pos[1] = gem_Vector(  2.5, 0, 0);
	pos[2] = gem_Vector(  0, 3, 0);
    pos[3] = gem_Vector(  0,-3, 0);
	pos[4] = gem_Vector(  -0.1f, 1, -2 );
	
	boob[0].pos =  GetD3DVECTOR( pos[0] );	
	boob[0].negative = FALSE;
	
	boob[1].pos =  GetD3DVECTOR( pos[1] );	
	boob[1].negative = TRUE;	

	boob[2].pos =  GetD3DVECTOR( pos[2] );	
	boob[2].negative = FALSE;

	boob[3].pos =  GetD3DVECTOR( pos[3] );		
	boob[3].negative = TRUE;

	boob[4].pos =  GetD3DVECTOR( pos[4] );	
	boob[4].negative = FALSE;

	InitGrid( g_Grid, GridPos, 25 );

	D3DVECTOR p1( 0.0f, 3.0f, 0.0f );
	D3DVECTOR p2( 3.0f,-3.0f, 0.0f );
	D3DVECTOR p3(-3.0f,-3.0f, 0.0f );	

	// Set the object material as yellow. We're setting the ambient color here
	// since this tutorial only uses ambient lighting. For apps that use real
	// lights, the diffuse and specular values should be set. (In addition, the
	// polygons' vertices need normals for true lighting.)
 

	// init backgroud "mesh"
	D3DVECTOR vFar = D3DVECTOR( 0.0f, 0.0f, 0.5f );
    Background[0] = D3DTLVERTEX( vFar, 0.5f, 0xFFFFFFFF, 0, 0.01f, 0.99f );
    Background[1] = D3DTLVERTEX( vFar, 0.5f, 0xFFFFFFFF, 0, 0.01f, 0.01f );
    Background[2] = D3DTLVERTEX( vFar, 0.5f, 0xFFFFFFFF, 0, 0.99f, 0.99f );
    Background[3] = D3DTLVERTEX( vFar, 0.5f, 0xFFFFFFFF, 0, 0.99f, 0.01f );

	LightBarVer[0] = D3DTLVERTEX( D3DVECTOR( 10, 470, 0.5f ), 0.5f, 0x70ffffff, 0, 0, 1 );
	LightBarVer[1] = D3DTLVERTEX( D3DVECTOR( 10,  10, 0.5f ), 0.5f, 0x70ffffff, 0, 0, 0 );
	LightBarVer[2] = D3DTLVERTEX( D3DVECTOR( 15, 470, 0.5f ), 0.5f, 0x70ffffff, 0, 1, 1 );
	LightBarVer[3] = D3DTLVERTEX( D3DVECTOR( 15,  10, 0.5f ), 0.5f, 0x70ffffff, 0, 1, 0 );

	LightBarHrz[0] = D3DTLVERTEX( D3DVECTOR( 10, 470, 0.5f ), 0.5f, 0x70ffffff, 0, 0, 1 );
	LightBarHrz[1] = D3DTLVERTEX( D3DVECTOR( 10,  10, 0.5f ), 0.5f, 0x70ffffff, 0, 0, 0 );
	LightBarHrz[2] = D3DTLVERTEX( D3DVECTOR( 15, 470, 0.5f ), 0.5f, 0x70ffffff, 0, 1, 1 );
	LightBarHrz[3] = D3DTLVERTEX( D3DVECTOR( 15,  10, 0.5f ), 0.5f, 0x70ffffff, 0, 1, 0 );

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

	Overground[0] = Background[0];
	Overground[1] = Background[1];
	Overground[2] = Background[2];
	Overground[3] = Background[3];		

	FadeV[0] = Background[0];
	FadeV[1] = Background[1];
	FadeV[2] = Background[2];
	FadeV[3] = Background[3];

	
	Plain[0] = D3DLVERTEX( D3DVECTOR(-11, 11, 3 ), 0x30FFFFFF, 0, 0, 0 );
	Plain[1] = D3DLVERTEX( D3DVECTOR( 11, 11, 3 ), 0x30FFFFFF, 0, 1, 0 );
	Plain[2] = D3DLVERTEX( D3DVECTOR(-11,-11, 3 ), 0x30FFFFFF, 0, 0, 1 );
	Plain[3] = D3DLVERTEX( D3DVECTOR( 11,-11, 3 ), 0x30FFFFFF, 0, 1, 1 );
	
	MirrorVerts[0][0] = D3DLVERTEX( D3DVECTOR( -3.5f,  3.5f, 7.5f ), 0xFFFFFF, 0, 0, 0 );
	MirrorVerts[0][1] = D3DLVERTEX( D3DVECTOR(  3.5f,  3.5f, 7.5f ), 0xFFFFFF, 0, 1, 0 );
	MirrorVerts[0][2] = D3DLVERTEX( D3DVECTOR( -3.5f, -3.5f, 7.5f ), 0xFFFFFF, 0, 0, 1 );
	MirrorVerts[0][3] = D3DLVERTEX( D3DVECTOR(  3.5f, -3.5f, 7.5f ), 0xFFFFFF, 0, 1, 1 );

	ClipVerts[0][0] = D3DLVERTEX( D3DVECTOR( -2.8f,  2.8f, 7.47f ), 0x80000000, 0, 0, 0 );
	ClipVerts[0][1] = D3DLVERTEX( D3DVECTOR(  2.8f,  2.8f, 7.47f ), 0x80000000, 0, 1, 0 );
	ClipVerts[0][2] = D3DLVERTEX( D3DVECTOR( -2.8f, -2.8f, 7.47f ), 0x80000000, 0, 0, 1 );
	ClipVerts[0][3] = D3DLVERTEX( D3DVECTOR(  2.8f, -2.8f, 7.47f ), 0x80000000, 0, 1, 1 );

	FLOAT		alpha = 0.5f*3.1415f;
	gem_Matrix	a;
	gem_Vector	vec;	

	for( int i = 1 ; i<4 ; i++, alpha+=0.5f*3.1415f )
	{
		a = RotationMtx( alpha, 0, 0 );			

		for( int j = 0 ; j<4 ; j++ )
		{
			vec.x = MirrorVerts[0][j].x;
			vec.y = MirrorVerts[0][j].y;
			vec.z = MirrorVerts[0][j].z;

			vec   = vec*a;

			MirrorVerts[i][j].x = vec.x;
			MirrorVerts[i][j].y = vec.y;
			MirrorVerts[i][j].z = vec.z;			

			MirrorVerts[i][j].tu =    MirrorVerts[0][j].tu;
			MirrorVerts[i][j].tv =    MirrorVerts[0][j].tv;
			MirrorVerts[i][j].color = MirrorVerts[0][j].color;

			vec.x = ClipVerts[0][j].x;
			vec.y = ClipVerts[0][j].y;
			vec.z = ClipVerts[0][j].z;

			vec   = vec*a;

			ClipVerts[i][j].x = vec.x;
			ClipVerts[i][j].y = vec.y;
			ClipVerts[i][j].z = vec.z;			

			ClipVerts[i][j].tu =    ClipVerts[0][j].tu;
			ClipVerts[i][j].tv =    ClipVerts[0][j].tv;
			ClipVerts[i][j].color = ClipVerts[0][j].color;
		}
	}

	
	Banner[0] = D3DLVERTEX( D3DVECTOR( 0, 2, 105 ), 0x80FFFFFF, 0, 0, 1 ); 
	Banner[1] = D3DLVERTEX( D3DVECTOR( 0, 2,  95 ), 0x80FFFFFF, 0, 1, 1 );
	Banner[2] = D3DLVERTEX( D3DVECTOR( 0,-2, 105 ), 0x80FFFFFF, 0, 0, 0 );
    Banner[3] = D3DLVERTEX( D3DVECTOR( 0,-2,  95 ), 0x80FFFFFF, 0, 1, 0 );	
			
	return S_OK;
}


//-----------------------------------------------------------------------------
// Name: App_FrameMove()
// Desc: Called once per frame, the call is used for animating the scene. The
//       device is used for changing various render states, and the timekey is
//       used for timing of the dynamics of the scene.
//-----------------------------------------------------------------------------
HRESULT fxFrameMove_Blobs( LPDIRECT3DDEVICE7 pd3dDevice, LPSYNCINFO sync )
{
	//******************************************************************	    
	D3DMATERIAL7       mtrl;
	ZeroMemory( &mtrl, sizeof(mtrl) );
    mtrl.dcvAmbient.r = 0.1f;
    mtrl.dcvAmbient.g = 0.1f;
    mtrl.dcvAmbient.b = 0.1f;
	mtrl.dcvDiffuse.r = 1.0f;
    mtrl.dcvDiffuse.g = 1.0f;
    mtrl.dcvDiffuse.b = 1.0f;
	mtrl.dcvDiffuse.a = 0.4f;
    pd3dDevice->SetMaterial( &mtrl );

	D3DLIGHT7			light;
	ZeroMemory( &light, sizeof(light) );
	light.dltType		= D3DLIGHT_POINT;
	light.dcvDiffuse.r	= 1.0f;
	light.dcvDiffuse.g	= 1.0f;
	light.dcvDiffuse.b	= 1.0f;
	light.dvPosition.x	= 0.0f;
	light.dvPosition.y	= 0.0f;
	light.dvPosition.z	= -10.0f;
	light.dvAttenuation0= 1.0f;
	light.dvRange		= D3DLIGHT_RANGE_MAX;	

	pd3dDevice->SetLight( 0, &light );
	
	pd3dDevice->LightEnable( 0, TRUE );
	// The view matrix defines the position and orientation of the camera.
	// Here, we are just moving it back along the z-axis by 10 units.
	D3DMATRIX matView = CameraMtx( gem_Vector( 0, 0, -10 ), gem_Vector( 0, 0, 20 ), 0 );//mat;
	//matView._43 = 10.0f;
    pd3dDevice->SetTransform( D3DTRANSFORMSTATE_VIEW, &matView );

	// 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 = GetD3DMATRIX( ProjectionMtx( 45.0f, 0.5f, 1000.0f, 0.70f ) );
	
    pd3dDevice->SetTransform( D3DTRANSFORMSTATE_PROJECTION, &matProj );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, TRUE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_AMBIENT, 0xFFFFFFFF );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ZENABLE, D3DZB_USEW );
	//****************************************************************************

	gem_Matrix		a = IdentMtx();
	FLOAT			rot[4], d = -1;	
	FLOAT			texCoord[4][2];
	FLOAT			fTimeKey = sync->fTimeKey;
	LONG			i, j;

	static FLOAT			sync0Coeff;
	static FLOAT			sync0Key;
	static DWORD			sync0;
	static FLOAT			sync1Key;
	static DWORD			sync1;
		
	DWORD	frame = ((DWORD)(fTimeKey*50.0f));

	if( sync->dwSync00 )
	{
		sync0 = 1;
		sync0Key = fTimeKey;
		sync->dwSync00 = 0;
	}

	if( sync->dwSync01 )
	{
		sync1 = 1;
		sync1Key = fTimeKey;
		sync->dwSync01 = 0;
	}

	if( fTimeKey>1.0f && fTimeKey < 9.0f )
	{
		FLOAT		value = fTimeKey -1.0f;

		boob[0].r = value>3.5f ? 3.5f : value;
		boob[1].r = value>3.0f ? 3.0f : value;
		boob[2].r = value>4.0f ? 4.0f : value;
		boob[3].r = value>5.5f ? 5.5f : value;
		boob[4].r = value>4.5f ? 4.5f : value;

		boob[0].R = value>4.0f ? 4.0f : value;
		boob[1].R = value>6.0f ? 6.0f : value;
		boob[2].R = value>5.0f ? 5.0f : value;
		boob[3].R = value>8.0f ? 8.0f : value;
		boob[4].R = value>8.0f ? 8.0f : value;
	}
	else
	{
		if( fTimeKey > 9.0f )
		{		
			boob[0].r = 3.5;
			boob[0].R = 4;
			boob[1].r = 3;
			boob[1].R = 6;		
			boob[2].r = 4;
			boob[2].R = 5;	
			boob[3].r = 5.5;
			boob[3].R = 8;	
			boob[4].r = 4.5;
			boob[4].R = 8;
		}
	}

	if( sync0 )
	{
		FLOAT		time = fTimeKey - sync0Key ;

		if( time < 0.4f )
		{
			sync0Coeff = 2.0f*time;
		}
		
		if( time >= 0.4f && time < 0.8f )
		{
			sync0Coeff = 1.6 - 2.0f*time;
		}	
		
		if( time > 0.8f )
		{
			sync0 = 0;
			sync0Coeff = 0;
		}		
	}
	else
	{
		sync0Coeff = 0;
	}

	if( fTimeKey < 4.0f )
	{
		sync0Coeff = 5.0f*( 4.0f - fTimeKey );
	}

	if( fTimeKey < 8.0f )
	{
		LightBarVer[0].sy = 480*fTimeKey*0.125f;
		LightBarVer[1].sy = 480*fTimeKey*0.125f - 460;
		LightBarVer[2].sy = 480*fTimeKey*0.125f;
		LightBarVer[3].sy = 480*fTimeKey*0.125f - 460;

		LightBarHrz[0].sx = -640*fTimeKey*0.125f + 640;
		LightBarHrz[1].sx = -640*fTimeKey*0.125f + 640;
		LightBarHrz[2].sx = 1280 - 640*fTimeKey*0.125f;		
		LightBarHrz[3].sx = 1280 - 640*fTimeKey*0.125f;
	}

	texCoord[0][0] = 0.0f;
	texCoord[0][1] = 1.0f;

	texCoord[1][0] = 0.0f;
	texCoord[1][1] = 0.0f;

	texCoord[2][0] = 1.0f;
	texCoord[2][1] = 1.0f;

	texCoord[3][0] = 1.0f;
	texCoord[3][1] = 0.0f;

	rot[0] = fTimeKey*1.75f;
	rot[1] = -fTimeKey*2.0f;
	rot[2] = -fTimeKey*1.0f;
	rot[3] = fTimeKey*1.5f;
	rot[4] = -fTimeKey*0.75f;

	for( i = 0; i<5 ; i++ )
	{
		a = RotationMtx( rot[i], rot[i], 0 );
		boob[i].pos = GetD3DVECTOR( pos[i]*a );
	}
	
	ZeroMemory( &g_matLocal, sizeof(D3DMATRIX) );

	if( sync1 )
	{
		FLOAT		time = fTimeKey - sync1Key ;

		if( time < 0.2f )
		{
			g_matLocal = (D3DMATRIX)( ScaleMtx( 1.0f + 1.5f*time)*RotationMtx( fTimeKey*1.0f, -fTimeKey*1.5f, fTimeKey*0.5f ) );
		}

		if( time >= 0.2f && time < 0.4f )
		{
			g_matLocal = (D3DMATRIX)( ScaleMtx( 1.6f - 1.5f*time)*RotationMtx( fTimeKey*1.0f, -fTimeKey*1.5f, fTimeKey*0.5f ) );
		}

		if( time >= 0.4f )
		{
			sync1 = 0;
			sync1Key = 0;
			g_matLocal = (D3DMATRIX)RotationMtx( fTimeKey*1.0f, -fTimeKey*1.5f, fTimeKey*0.5f );
		}
	}
	else
	{
		g_matLocal = (D3DMATRIX)RotationMtx( fTimeKey*1.0f, -fTimeKey*1.5f, fTimeKey*0.5f );		
	}

	for( i = 0 ; i<5 ; i++ )
	{
		lbVerPos[2*i]	= 40.0f + ( 1.0f + (FLOAT)sin( 0.5f*fTimeKey*0.31f*(FLOAT)(i+1) + i ) )*20.0f;
		lbVerPos[2*i+1] = 40.0f + ( 1.0f + (FLOAT)cos( 0.5f*fTimeKey*0.15f*(FLOAT)(i+1) - (FLOAT)i*0.5f ) )*20.0f;
		lbHrzPos[2*i]	= 400.0f + ( 1.0f + (FLOAT)cos( 0.5f*fTimeKey + i ) )*20.0f;
		lbHrzPos[2*i+1] = 400.0f +( 1.0f + (FLOAT)sin( 0.5f*fTimeKey*0.25f*(FLOAT)(i+1) - i ) )*20.0f;
	}

	gem_Vector		vec;

	gem_Vector	syncVec[4];

	syncVec[0] = gem_Vector(  0,  0,  8 );
	syncVec[1] = gem_Vector(  8,  0,  0 );
	syncVec[2] = gem_Vector(  0,  0, -8 );
	syncVec[3] = gem_Vector( -8,  0,  0 );
	
	for( i = 0 ; i<4 ; i++ )
	{
		if( fTimeKey < 4 )
		{
			a = RotationMtx( 0, 3.14159f*0.5f, 0 );
		}
		else
		{
			a = RotationMtx( -(fTimeKey - 4)*0.25f, (fTimeKey-4)*0.6f + 3.14159f*0.5f, (fTimeKey-4)*1.05f );
		}

		for( j = 0 ; j<4 ; j++ )
		{
			vec.x = MirrorVerts[i][j].x + syncVec[i].x*sync0Coeff;
			vec.y = MirrorVerts[i][j].y + syncVec[i].y*sync0Coeff;
			vec.z = MirrorVerts[i][j].z + syncVec[i].z*sync0Coeff;

			vec   = vec*a;

			MirrorPlain[i][j].x = vec.x;
			MirrorPlain[i][j].y = vec.y;
			MirrorPlain[i][j].z = vec.z;

			MirrorPlain[i][j].tu = MirrorVerts[i][j].tu;
			MirrorPlain[i][j].tv = MirrorVerts[i][j].tv;
			MirrorPlain[i][j].color = MirrorVerts[i][j].color;

			vec.x = ClipVerts[i][j].x + syncVec[i].x*sync0Coeff;
			vec.y = ClipVerts[i][j].y + syncVec[i].y*sync0Coeff;
			vec.z = ClipVerts[i][j].z + syncVec[i].z*sync0Coeff;

			vec   = vec*a;

			ClipPlain[i][j].x = vec.x;
			ClipPlain[i][j].y = vec.y;
			ClipPlain[i][j].z = vec.z;

			ClipPlain[i][j].tu = ClipVerts[i][j].tu;
			ClipPlain[i][j].tv = ClipVerts[i][j].tv;
			ClipPlain[i][j].color = ClipVerts[i][j].color;						
		}

		Background[i].tu = texCoord[i][0] + (FLOAT)sin( fTimeKey*0.05f );
		Background[i].tv = texCoord[i][1] + (FLOAT)cos( fTimeKey*0.05f );
	}	

	alpha = fTimeKey*0.25f>1.0f ? 1.0f : fTimeKey*0.25f;	

	for( i = 0 ; i<10 ; i++ )
	{
		matBackLocal[i] = (D3DMATRIX)( RotationMtx( 0.0f, 0.0f, -(1.0f+(FLOAT)i/10.0f)*(fTimeKey+5.0f)*0.275f )*
										TranslationMtx( 0.0f, 0.0f, 2.0f*i+3)  );
	}


	FLOAT		val;		

	for( i = 0 ; i<8 ; i++ )
	{		
		val = (FLOAT)fmod( 20*fTimeKey+i*20.0f, 160.0f );

		matBannerLocal[i] = GetD3DMATRIX( TranslationMtx( gem_Vector( 0, 0, -100.0f ) )*
				  						  TranslationMtx( gem_Vector( 0, 0, -val ) )*
										  RotationMtx( -3.1415f*3.0f/180.0f, 0.0f, 0.0f )*
										  TranslationMtx( gem_Vector( 0, 0, 100.0f ) ) );
	}

	Fade = 0;	
	DWORD	aph;

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

		aph = (DWORD)( ( 1.0f - fTimeKey )*255.0f );	

		if( aph > 255 ) 
			aph = 255;

		aph <<= 24;

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

	if( fTimeKey >= 22.0f && fTimeKey < 32.0f )
	{	
		text1 = 1;

		if( fTimeKey < 25.0f)
		{		
			text1_alpha = (DWORD)((fTimeKey - 22.0f)*128.0f*0.333f);
		}
		else
		{
			if( fTimeKey > 28.0f )
			{
				text1_alpha = (DWORD)(( 32.0f - fTimeKey)*255.0f*0.25f);
			}
			else
				text1_alpha = 128;
		}

		if( fTimeKey < 25.0f )
		{
			stretch = 1;
			sizey = 140.0f + (25.0f - fTimeKey)*45.0f;
		}
		else
		{		
			stretch = 0;
			
			if( fTimeKey < 29.0f )
				text1_alpha = 255;
		}

		if( fTimeKey > 24.5f )
		{	
			for( i = 0 ; i < 5 ; i++ )
			{			
				b_alpha[i] = 0;			

				if( fTimeKey > 24.5f + (FLOAT)i*0.3f )
				{
					b_sizex[i] = fmod( fTimeKey - (24.5f + (FLOAT)i*0.3f), 2.0f )*55.0f;
					b_alpha[i] = (2.0f - fmod( fTimeKey - (24.5f + (FLOAT)i*0.3f), 2.0f ))*30.0f;			
				}
			}	

			blur = 1;
		}
		else
			blur = 0;
	}
	else
		text1 = 0;

	if( fTimeKey > 6.0f && fTimeKey<16.0f )
	{
		tx2size = (fTimeKey-6.0f)*14.0f;
		text2_alpha = 200.0f*sinf( (fTimeKey - 6.0f)*3.1415*0.1 );		
		text2 = 1;
	}
	else
		text2 = 0;

	
	return S_OK;
}


//-----------------------------------------------------------------------------
// Name: App_Render()
// Desc: Renders the scene. This tutorial draws a bunch of intersecting
//       triangles that are rotating about the y-axis. Without z-buffering,
//       the polygons could not be drawn correctly (unless the app performed
//       complex polygon-division routines and sorted the polygons in back-to-
//       front order.)
//-----------------------------------------------------------------------------
HRESULT fxRender_Blobs( LPDIRECT3DDEVICE7 pd3dDevice )
{
    // Clear the viewport to a blue color. Also "clear" the z-buffer to the
	// value 1.0 (which represents the far clipping plane).	
	HRESULT					hr;
	D3DMATERIAL7			mtrl;	
	DWORD					nbr1, nbr2;	

	LONG					i, j;

    hr = pd3dDevice->Clear( 1UL, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0L );	

	D3DMATRIX	matTrn = GetD3DMATRIX( TranslationMtx( gem_Vector( -7, 0, 20 ) ) );
	D3DMATRIX	matWorld;
	D3DMATRIX   mat    = GetD3DMATRIX( IdentMtx() );
	
	// The world matrix controls the position and orientation of the polygons
	// in world space. We'll use it later to spin the triangle.

    matWorld = g_matLocal;

    // Begin the scene		
	
	Calculate( g_Grid, boob, 5 );
	nbr1 = CalculateVertex( g_Grid, boob, 5, vertab1, TRUE );	
	nbr2 = CalculateVertex( g_Grid, boob, 5, vertab2, FALSE );		   

	pd3dDevice->BeginScene();

	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_SHADEMODE, D3DSHADE_GOURAUD );

	pd3dDevice->SetRenderState( D3DRENDERSTATE_WRAP0, FALSE ); 	
	

	pd3dDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, FALSE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_NONE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, TRUE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE );			
	pd3dDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, FALSE );
	pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );

	pd3dDevice->SetTexture( 0, GetTexture( "data\\textures\\nopee1.jpg" ) );
		
	for( i = 0 ; i<7 ; i++ )
	{		
		pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &matBackLocal[i] );		
		pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, Plain, 4, NULL );
	}	

	pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA );
			
	pd3dDevice->SetTexture( 0, mask );	

	pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );	
	pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, D3DFVF_TLVERTEX, Background, 4, 0 );	
	pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );
	
	pd3dDevice->SetTexture( 0, GetTexture( "data\\textures\\efxx.jpg" ) );	
	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE );

	for( i = 0 ; i<10 ; i++ )
	{
		LightBarVer[0].sx = lbVerPos[i];
		LightBarVer[1].sx = lbVerPos[i];
		LightBarVer[2].sx = lbVerPos[i] + 12;
		LightBarVer[3].sx = lbVerPos[i] + 12;

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

		LightBarHrz[0].sy = lbHrzPos[i] + 12;
		LightBarHrz[1].sy = lbHrzPos[i];
		LightBarHrz[2].sy = lbHrzPos[i] + 12;		
		LightBarHrz[3].sy = lbHrzPos[i];

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

	pd3dDevice->SetTexture( 0, mask );
	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA );
		
	
	for( i = 0 ; i<10 ; i++ )
	{
		pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &matBannerLocal[i] );		
		pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, Banner, 4, 0 );
	}	
	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE );

	pd3dDevice->SetTexture( 0, GetTexture( "data\\textures\\tyl.bmp" ) );	

	pd3dDevice->GetMaterial( &mtrl );
	mtrl.dcvDiffuse.a = alpha*0.35f;
	pd3dDevice->SetMaterial( &mtrl );	
	
	for( i = 0 ; i<4; i++ )
	{		
		pd3dDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, TRUE );		
		pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, FALSE );		
		pd3dDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, FALSE );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_CLIPPLANEENABLE, 0x00 );		

		pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &matTrn );

		pd3dDevice->SetTexture( 0, NULL );

		MirrorPlain[i][0].dcColor = 0x0; MirrorPlain[i][1].dcColor = 0x0;
		MirrorPlain[i][2].dcColor = 0x0; MirrorPlain[i][3].dcColor = 0x0;

		pd3dDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, FALSE );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_CCW );

		pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, MirrorPlain[i], 4, NULL );		

		MirrorPlain[i][0].dcColor = 0xffffff; MirrorPlain[i][1].dcColor = 0xffffff;
		MirrorPlain[i][2].dcColor = 0xffffff; MirrorPlain[i][3].dcColor = 0xffffff;

		pd3dDevice->SetTexture( 0, GetTexture( "data\\textures\\tyl.bmp" ) );
		
		pd3dDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, TRUE );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_CW );

		pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, MirrorPlain[i], 4, NULL );				

		D3DMATRIX  matMirror;
		
		gem_Vector a = gem_Vector( ClipPlain[i][0].x, ClipPlain[i][0].y, ClipPlain[i][0].z );
		gem_Vector b = gem_Vector( ClipPlain[i][1].x, ClipPlain[i][1].y, ClipPlain[i][1].z );
		gem_Vector c = gem_Vector( ClipPlain[i][3].x, ClipPlain[i][3].y, ClipPlain[i][3].z );
		gem_Vector d = gem_Vector( ClipPlain[i][2].x, ClipPlain[i][2].y, ClipPlain[i][2].z ); 		

		gem_Vector n = Normalize( Cross( b-a, c-a ) );
		gem_Vector o = ( a + b + c + d )*0.25;

		MirrorMtx( matMirror, n, Length( o ) );

		matMirror = matWorld*matMirror*matTrn;

		gem_Matrix mtxTrn = TranslationMtx( -7, 0, 20 );
		a = a*mtxTrn;
		b = b*mtxTrn;
		c = c*mtxTrn;
		d = d*mtxTrn;

		FLOAT plane[4];
		pd3dDevice->SetClipPlane( 0, CreatePlane( plane, a, b, gem_Vector( 0, 0, -10 ) ) );
		pd3dDevice->SetClipPlane( 1, CreatePlane( plane, b, c, gem_Vector( 0, 0, -10 ) ) );
		pd3dDevice->SetClipPlane( 2, CreatePlane( plane, c, d, gem_Vector( 0, 0, -10 ) ) );
		pd3dDevice->SetClipPlane( 3, CreatePlane( plane, d, a, gem_Vector( 0, 0, -10 ) ) );

		pd3dDevice->SetRenderState( D3DRENDERSTATE_CLIPPLANEENABLE, 0x0f );				

		pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &matMirror );
		ApplySphereMap( vertab1, nbr1, pd3dDevice );
		ApplySphereMap( vertab2, nbr2, pd3dDevice );

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

		pd3dDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, TRUE );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, FALSE );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, TRUE );			
		pd3dDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_NONE );

		pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, D3DFVF_VERTEX, vertab1, nbr1, NULL );
				
		pd3dDevice->SetTexture( 0, GetTexture( "data\\textures\\blobo.jpg" ) );
	
		pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, TRUE );	
		pd3dDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, FALSE );				
		pd3dDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, FALSE );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_NONE );

		pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, D3DFVF_VERTEX, vertab2, nbr2, NULL );

		pd3dDevice->SetRenderState( D3DRENDERSTATE_CLIPPLANEENABLE, 0x00 );	

		pd3dDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, FALSE );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA );
		pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &matTrn );

		pd3dDevice->SetTexture( 0, NULL );

		pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, ClipPlain[i], 4, NULL );

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

		pd3dDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, TRUE );		
		pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, TRUE );		
		pd3dDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, FALSE );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_CLIPPLANEENABLE, 0x00 );		

		pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &matTrn );

		pd3dDevice->SetTexture( 0, GetTexture( "data\\textures\\ramka.bmp" ) );

		pd3dDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, FALSE );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_CCW );

		pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, MirrorPlain[i], 4, NULL );		
				
	}

	mtrl.dcvDiffuse.a = alpha;
	pd3dDevice->SetMaterial( &mtrl );
	pd3dDevice->SetTexture( 0, GetTexture( "data\\textures\\blobo.jpg" ) );	
	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_CLIPPLANEENABLE, 0x00 );	

	matWorld = matWorld*matTrn;

	pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &matWorld );
	ApplySphereMap( vertab1, nbr1, pd3dDevice );
	ApplySphereMap( vertab2, nbr2, pd3dDevice );
	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, FALSE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, TRUE );		
	pd3dDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, TRUE );

	pd3dDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_NONE );
	pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, D3DFVF_VERTEX, vertab1, nbr1, NULL );		

	pd3dDevice->SetTexture( 0, GetTexture( "data\\textures\\env.jpg" ) );				
	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, TRUE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, FALSE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, TRUE );

	pd3dDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_NONE );
	pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, D3DFVF_VERTEX, vertab2, nbr2, NULL );		

	pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
	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_Blobs.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 );
	//pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );

	if( text1 )
	{	
		RenderEfxFace( 400, 120, 403, 140, text1_alpha, GetTexture( "data\\texts\\napis_1.jpg" ), pd3dDevice );

		if( stretch )
		{
			RenderEfxFace( 400, 120, 403, sizey, text1_alpha, GetTexture( "data\\texts\\napis_1.jpg" ), pd3dDevice );
		}

		if( blur )
		{
			for( i = 0 ; i<5 ; i++ )
			{
				if( text1_alpha < b_alpha[i] )
					b_alpha[i] = text1_alpha;

				RenderEfxFace( 400, 120, 403 + b_sizex[i], 140, b_alpha[i], GetTexture( "data\\texts\\napis_1.jpg" ), pd3dDevice );
			}
		}
	}

	if( text2 )
	{
		RenderEfxFace( 200, 320, 241 + tx2size, 137 + tx2size, text2_alpha, GetTexture( "data\\texts\\napis_10.jpg" ), pd3dDevice );
	}

	pd3dDevice->SetTexture( 0, NULL );	

	if( Fade )
	{		
		pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, D3DFVF_TLVERTEX, FadeV, 4, 0 );				
	}	

	

	pd3dDevice->EndScene();	

    return S_OK;
}

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

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