//----------------------------------------------------------------------------------------------
// real time object generation and morphing, uuuu tentacles wow not so bad indeed
// well this part is coded by fella known as acid|z51 (hey he make reost of the code too,
// this is strange :))
//----------------------------------------------------------------------------------------------
// this file is part of source code from intertia³ demo (c)zone51 `2000
//----------------------------------------------------------------------------------------------

#define  D3D_OVERLOADS
#include "tentacleEfx.h"
#include "directgem.h"
#include "volumetric.h"
#include "object3d.h"
#include "enum.h"
#include "extrastuff.h"

#define		NUM_TENTACLES		22

static		LPDIRECTDRAWSURFACE7	text[2] = { NULL, NULL };
static		LPDIRECTDRAWSURFACE7	zbuffer1 = NULL;
static		LPDIRECTDRAWSURFACE7	zbuffer2 = NULL;

static		gem_Vector				B[NUM_TENTACLES][4];			// beziers controls 
static		gem_Vector				BE[NUM_TENTACLES][4];			// beziers controls 
static		D3DVERTEX				tentacles[NUM_TENTACLES][600];
static		gem_Vector*				curTent;
static		gem_Vector				vertex[NUM_TENTACLES][100];

static		D3DMATRIX				matTentacles;
static		D3DLVERTEX				Flare[4];
static		D3DLVERTEX				Plate[4];

static		D3DLVERTEX				PTunnel[1200];					// tunnel faces
static		WORD					PTunnelInd[1800];

static		D3DTLVERTEX				BlurFace[4];
static		D3DTLVERTEX				BlurFace2[4];

static		D3DTLVERTEX				Circle[101];
static		DWORD					renderSpiral;


static		D3DVIEWPORT7			view;

static		gem_Matrix				mtxFlarez;

static		FLOAT					speedup = 0;

static		DWORD					renderFlarez;

static		FLOAT					sync0Start = -50.0f;
static		FLOAT					sync1Start = -50.0f;
static		FLOAT					sync2Start = -50.0f;
static		FLOAT					sync3Start = -50.0f;
static		FLOAT					sync4Start = -50.0f;

static		D3DTLVERTEX				Overground[4];

static		DWORD					blurpage = 0;

static		DWORD					text1 = 0;
static		FLOAT					tx1size;
static		DWORD					text1_alpha;

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


#define		rnd()				(((FLOAT)rand()-(FLOAT)rand())/(2L*RAND_MAX))
#define		G_PI				3.14159f

#define sqr( x ) ((x)*(x))

gem_Vector Bezier( FLOAT t, gem_Vector* B )
{
	FLOAT		_1t = 1-t;
	FLOAT		_1t2 = _1t*_1t;
	FLOAT		_1t3 = _1t2*_1t;
	FLOAT		t2 = t*t;
	FLOAT		t3 = t2*t;

	return	B[0]*_1t3 + 3*B[1]*t*_1t2 + 3*B[2]*t2*_1t + B[3]*t3;
}

gem_Vector DerivBezier( FLOAT t, gem_Vector* B )
{
	return Normalize( -3*B[0]*sqr(1-t) + 3*B[1]*(t-1)*(3*t-1) - 3*B[2]*t*(3*t-2) + 3*B[3]*sqr(t) );
}

DWORD CreateTentacle( LPD3DVERTEX vert, gem_Vector* B, FLOAT baseR )
{
	DWORD		i, j, ii = 0;
	DWORD		num = 0;
	FLOAT		r1, r2;
	FLOAT		alpha;

	gem_Vector	segment1[10];
	gem_Vector	segment2[10];

	gem_Vector	pos1, pos2, pos3;
	gem_Vector	tng1, tng2;	

	gem_Matrix	mtx1, mtx2;

	D3DVECTOR	n = D3DVECTOR( 0, 0, 0 );

	for( i = 0 ; i<9 ; i++ )
	{
		pos1 = Bezier( (FLOAT)i*0.1f, B );
		pos2 = Bezier( (FLOAT)(i+1)*0.1f, B );
		//pos3 = Bezier( (FLOAT)(i+2)*0.1f, B );		

		r1   = baseR*expf(-0.2f*(FLOAT)i);//(1 - (FLOAT)i*0.1f); 
		//r1   = baseR*(1 - (FLOAT)i*0.1f); 
		mtx1 = InvCameraMtx( gem_Vector( 0, 0, 0 ), DerivBezier( (FLOAT)i*0.1f, B ), 30 )*TranslationMtx( pos1 );
		//mtx1 = InvCameraMtx( pos1, pos2, 0 )*TranslationMtx( pos1 );

		r2   = baseR*expf(-0.2f*(FLOAT)(i+1));//(1 - (FLOAT)(i+1)*0.1f); 				

		//r2   = baseR*(1 - (FLOAT)(i+1)*0.1f); 				
		mtx2 = InvCameraMtx( gem_Vector( 0, 0, 0 ), DerivBezier( (FLOAT)(i+1)*0.1f, B ), 30 )*TranslationMtx( pos2 );

		

		for( j = 0 ; j<10 ; j++ )
		{
			alpha = (FLOAT)j*6.28f/10.0f;
			segment1[j] = gem_Vector( r1*cosf( alpha ), r1*sinf( alpha ), 0 )*mtx1;
			segment2[j] = gem_Vector( r2*cosf( alpha ), r2*sinf( alpha ), 0 )*mtx2;
			curTent[ii++] = gem_Vector( r1*cosf( alpha ), r1*sinf( alpha ), 0 )*ScaleMtx( 1.3f )*mtx1;
		}

		for( j = 0 ; j<9 ; j++ )
		{
			vert[num++] = D3DVERTEX( D3DVECTOR( segment1[j].x, segment1[j].y, segment1[j].z ), n, (FLOAT)j*0.1f, (FLOAT)i*0.1f );
			vert[num++] = D3DVERTEX( D3DVECTOR( segment1[j+1].x, segment1[j+1].y, segment1[j+1].z ), n, (FLOAT)(j+1)*0.1f, (FLOAT)i*0.1f );
			vert[num++] = D3DVERTEX( D3DVECTOR( segment2[j+1].x, segment2[j+1].y, segment2[j+1].z ), n, (FLOAT)(j+1)*0.1f, (FLOAT)(i+1)*0.1f );

			vert[num++] = D3DVERTEX( D3DVECTOR( segment1[j].x, segment1[j].y, segment1[j].z ), n, (FLOAT)j*0.1f, (FLOAT)i*0.1f );
			vert[num++] = D3DVERTEX( D3DVECTOR( segment2[j+1].x, segment2[j+1].y, segment2[j+1].z ), n, (FLOAT)(j+1)*0.1f, (FLOAT)(i+1)*0.1f );
			vert[num++] = D3DVERTEX( D3DVECTOR( segment2[j].x, segment2[j].y, segment2[j].z ), n, (FLOAT)j*0.1f, (FLOAT)(i+1)*0.1f );
		}

		vert[num++] = D3DVERTEX( D3DVECTOR( segment1[9].x, segment1[9].y, segment1[9].z ), n, 0.9f, (FLOAT)i*0.1f );
		vert[num++] = D3DVERTEX( D3DVECTOR( segment1[0].x, segment1[0].y, segment1[0].z ), n, 1.0f, (FLOAT)i*0.1f );
		vert[num++] = D3DVERTEX( D3DVECTOR( segment2[0].x, segment2[0].y, segment2[0].z ), n, 1.0f, (FLOAT)(i+1)*0.1f );

		vert[num++] = D3DVERTEX( D3DVECTOR( segment1[9].x, segment1[9].y, segment1[9].z ), n, 0.9f, (FLOAT)i*0.1f );
		vert[num++] = D3DVERTEX( D3DVECTOR( segment2[0].x, segment2[0].y, segment2[0].z ), n, 1.0f, (FLOAT)(i+1)*0.1f );
		vert[num++] = D3DVERTEX( D3DVECTOR( segment2[9].x, segment2[9].y, segment2[9].z ), n, 0.9f, (FLOAT)(i+1)*0.1f );

	}

	for( j = 0 ; j<9 ; j++ )
	{
		alpha = (FLOAT)j*6.28f/10.0f;
		curTent[ii++] = gem_Vector( r2*cosf( alpha ), r2*sinf( alpha ), 0 )*ScaleMtx( 1.3f )*mtx2;
		vert[num++] = D3DVERTEX( D3DVECTOR( segment2[j].x, segment2[j].y, segment2[j].z ), n, (FLOAT)j*0.1f, 0.9f );
		vert[num++] = D3DVERTEX( D3DVECTOR( segment2[j+1].x, segment2[j+1].y, segment2[j+1].z ), n, (FLOAT)j*0.1f, 0.9f );
		vert[num++] = D3DVERTEX( D3DVECTOR( B[3].x, B[3].y, B[3].z ), n, (FLOAT)j*0.1f, 1.0f );		
	}

	alpha = (FLOAT)9*6.28f/10.0f;
	curTent[ii++] = gem_Vector( r2*cosf( alpha ), r2*sinf( alpha ), 0 )*ScaleMtx( 1.3f )*mtx2;

	vert[num++] = D3DVERTEX( D3DVECTOR( segment2[9].x, segment2[9].y, segment2[9].z ), n, 0.9f, 0.9f );
	vert[num++] = D3DVERTEX( D3DVECTOR( segment2[0].x, segment2[0].y, segment2[0].z ), n, 1.0f, 0.9f );
	vert[num++] = D3DVERTEX( D3DVECTOR( B[3].x, B[3].y, B[3].z ), n, 0.95f, 1.0f );	

	return num;
}

#define TEXTSIZE	256

HRESULT fxInit_TentacleEfx( LPDIRECT3DDEVICE7 pd3dDevice )
{	
	DWORD					i, j;

	D3DVECTOR vFar = D3DVECTOR( 0.0f, 0.0f, 0.5f );
	
	BlurFace2[0] = D3DTLVERTEX( vFar, 0.5f, 0xb0ffffff, 0, 0, 1 );
	BlurFace2[1] = D3DTLVERTEX( vFar, 0.5f, 0xb0ffffff, 0, 0, 0 );
	BlurFace2[2] = D3DTLVERTEX( vFar, 0.5f, 0xb0ffffff, 0, 1, 1 );
	BlurFace2[3] = D3DTLVERTEX( vFar, 0.5f, 0xb0ffffff, 0, 1, 0 );    

	LPDIRECTDRAWSURFACE7	surf;	

	DDSURFACEDESC2			ddsd;
	LPDIRECTDRAW7			pDD;
	HRESULT					hr;

	// create a texture buffer 	

	ddsd.dwSize = sizeof( ddsd );
	pd3dDevice->GetRenderTarget( &surf );
	surf->GetSurfaceDesc( &ddsd );
	surf->GetDDInterface( (LPVOID*)&pDD );

	ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH;
	ddsd.ddsCaps.dwCaps = DDSCAPS_TEXTURE | DDSCAPS_3DDEVICE;
	ddsd.dwHeight	= TEXTSIZE;
	ddsd.dwWidth	= TEXTSIZE;

	view.dwWidth	= ddsd.dwWidth;
	view.dwHeight	= ddsd.dwHeight;
	view.dwX		= 0;
	view.dwY		= 0;
    view.dvMaxZ     = 1.0f;
	view.dvMinZ		= 0.0f;

	BlurFace2[0].sy = (FLOAT)view.dwHeight;
    BlurFace2[2].sy = (FLOAT)view.dwHeight;
    BlurFace2[2].sx = (FLOAT)view.dwWidth;
    BlurFace2[3].sx = (FLOAT)view.dwWidth;	    

	hr = pDD->CreateSurface( &ddsd, &text[0], 0 );
	hr = pDD->CreateSurface( &ddsd, &text[1], 0 );

	pd3dDevice->GetRenderTarget( &surf );

	DDSCAPS2			ddcaps = { DDSCAPS_ZBUFFER };

	hr = surf->GetAttachedSurface( &ddcaps, &zbuffer1 );

	surf->Release();
	
	zbuffer1->GetSurfaceDesc( &ddsd );

	ddsd.dwWidth	= TEXTSIZE;
	ddsd.dwHeight	= TEXTSIZE;

	zbuffer1->Release();

	ddsd.dwFlags = DDSD_CAPS | DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
	ddsd.ddsCaps.dwCaps = DDSCAPS_ZBUFFER;

	hr = pDD->CreateSurface( &ddsd, &zbuffer1, 0 );
	text[0]->AddAttachedSurface( zbuffer1 );

	hr = pDD->CreateSurface( &ddsd, &zbuffer2, 0 );
	text[1]->AddAttachedSurface( zbuffer2 );

	LoadTexture( "data\\textures\\tent.jpg", pd3dDevice );		
	LoadTexture( "data\\textures\\toonel.jpg", pd3dDevice );
	LoadTexture( "data\\textures\\part.jpg", pd3dDevice );
	LoadTexture( "data\\texts\\napis_11.jpg", pd3dDevice );
	LoadTexture( "data\\texts\\napis_7.jpg", pd3dDevice );

	LoadTexture( "data\\textures\\fg_Tentacle.jpg", pd3dDevice );	
	surf = GetTexture( "data\\textures\\fg_Tentacle.jpg" );
	LoadAlphaChannel( "data\\textures\\fg_Tentacle_alpha.bmp", &surf, pd3dDevice, 0 );
	
	Flare[0] = D3DLVERTEX( D3DVECTOR(-0.2, 0.2, 0 ), 0xffffffff, 0, 0, 0 );
	Flare[1] = D3DLVERTEX( D3DVECTOR( 0.2, 0.2, 0 ), 0xffffffff, 0, 1, 0 );
	Flare[2] = D3DLVERTEX( D3DVECTOR(-0.2,-0.2, 0 ), 0xffffffff, 0, 0, 1 );
	Flare[3] = D3DLVERTEX( D3DVECTOR( 0.2,-0.2, 0 ), 0xffffffff, 0, 1, 1 );

	Plate[0] = D3DLVERTEX( D3DVECTOR(-5, -25,  20 ), 0x80ffffff, 0, 0, 0 );
	Plate[1] = D3DLVERTEX( D3DVECTOR( 5, -25,  20 ), 0x80ffffff, 0, 1, 0 );
	Plate[2] = D3DLVERTEX( D3DVECTOR(-5, -25, 0 ), 0x80ffffff, 0, 0, 1 );
	Plate[3] = D3DLVERTEX( D3DVECTOR( 5, -25, 0 ), 0x80ffffff, 0, 1, 1 );	

	BlurFace[0] = D3DTLVERTEX( vFar, 0.5f, 0x60ffffff, 0, 0, 0 );
	BlurFace[1] = D3DTLVERTEX( vFar, 0.5f, 0x60ffffff, 0, 1, 0 );
	BlurFace[2] = D3DTLVERTEX( vFar, 0.5f, 0x60ffffff, 0, 0, 1 );
	BlurFace[3] = D3DTLVERTEX( vFar, 0.5f, 0x60ffffff, 0, 1, 1 );    		

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

	D3DVIEWPORT7 vp;
    pd3dDevice->GetViewport(&vp);
    BlurFace[0].sy = (FLOAT)vp.dwHeight;
    BlurFace[2].sy = (FLOAT)vp.dwHeight;
    BlurFace[2].sx = (FLOAT)vp.dwWidth;
    BlurFace[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;

	for( i = 0 ; i < NUM_TENTACLES ; i++ )
	{
		B[i][0] = gem_Vector( 0, 0, 0 );
		B[i][1] = 15*Normalize( gem_Vector( rnd(), rnd(), rnd() ) );
		B[i][2] = 15*Normalize( gem_Vector( rnd(), rnd(), rnd() ) );
	}	

	for( i = 0 ; i<2 ; i++ )
	{
		FLOAT alpha = (FLOAT)i*3.1415f/6.0f;

		B[i*10+0][3] = gem_Vector( 30.0f*cosf(G_PI*0.166f), 30*sinf(G_PI*0.166f), 0 )*RotationMtx( 0, alpha, 0 );
		B[i*10+1][3] = gem_Vector( 30.0f*cosf(G_PI*0.333f), 30*sinf(G_PI*0.333f), 0 )*RotationMtx( 0, alpha, 0 );
		B[i*10+2][3] = gem_Vector( 30.0f*cosf(G_PI*0.500f), 30*sinf(G_PI*0.500f), 0 )*RotationMtx( 0, alpha, 0 );
		B[i*10+3][3] = gem_Vector( 30.0f*cosf(G_PI*0.666f), 30*sinf(G_PI*0.666f), 0 )*RotationMtx( 0, alpha, 0 );
		B[i*10+4][3] = gem_Vector( 30.0f*cosf(G_PI*0.833f), 30*sinf(G_PI*0.833f), 0 )*RotationMtx( 0, alpha, 0 );
		B[i*10+5][3] = gem_Vector( 30.0f*cosf(G_PI*1.166f), 30*sinf(G_PI*1.166f), 0 )*RotationMtx( 0, alpha, 0 );
		B[i*10+6][3] = gem_Vector( 30.0f*cosf(G_PI*1.333f), 30*sinf(G_PI*1.333f), 0 )*RotationMtx( 0, alpha, 0 );
		B[i*10+7][3] = gem_Vector( 30.0f*cosf(G_PI*1.500f), 30*sinf(G_PI*1.500f), 0 )*RotationMtx( 0, alpha, 0 );
		B[i*10+8][3] = gem_Vector( 30.0f*cosf(G_PI*1.666f), 30*sinf(G_PI*1.666f), 0 )*RotationMtx( 0, alpha, 0 );
		B[i*10+9][3] = gem_Vector( 30.0f*cosf(G_PI*1.833f), 30*sinf(G_PI*1.833f), 0 )*RotationMtx( 0, alpha, 0 );		
	}

	B[20][3] = gem_Vector( 40, 0, 0 );
	B[21][3] = gem_Vector( -40, 0, 0 );
	
	for( i = 0 ; i < NUM_TENTACLES ; i++ )
	{
		BE[i][0] = B[i][0];
		BE[i][1] = B[i][1];
		BE[i][2] = B[i][2];
		BE[i][3] = B[i][3];
	}

	for( i = 0, j = 0 ; i<300 ; i++ )
	{
		PTunnelInd[j++] = i*4 + 0;
		PTunnelInd[j++] = i*4 + 1;
		PTunnelInd[j++] = i*4 + 2;
		PTunnelInd[j++] = i*4 + 1;
		PTunnelInd[j++] = i*4 + 2;
		PTunnelInd[j++] = i*4 + 3;

		PTunnel[i*4+0] = Plate[0];
		PTunnel[i*4+1] = Plate[1];
		PTunnel[i*4+2] = Plate[2];
		PTunnel[i*4+3] = Plate[3];
	}	

	for( i = 0 ; i < 101 ; i++ )
		Circle[i] = D3DTLVERTEX( vFar, 0.5f, 0, 0, 0, 0 );

	Circle[0].sx = 320;
	Circle[0].sy = 240;

	return S_OK;
}

HRESULT fxFrameMove_TentacleEfx( LPDIRECT3DDEVICE7 pd3dDevice, LPSYNCINFO sync )
{

	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 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 = 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 = (D3DMATRIX)ProjectionMtx( 50.0f, 1.0f, 1000.0f, 0.70f );
	pd3dDevice->SetTransform( D3DTRANSFORMSTATE_PROJECTION, &matProj );	

	//****************************************************************************
	
	FLOAT		fTimeKey = sync->fTimeKey*0.1f;		
	FLOAT		fTime = sync->fTimeKey;		
	DWORD		i;
	
	FLOAT				scale = 1.0f;
	FLOAT				scale2 = 1.0f;

	if( sync->dwSync00 )
	{
		sync0Start = fTime;
		sync->dwSync00 = 0;
	}

	if( sync->dwSync01 )
	{
		sync1Start = fTime;
		sync->dwSync01 = 0;
	}

	if( sync->dwSync02 )
	{
		sync2Start = fTime;
		sync->dwSync02 = 0;
	}

	if( sync->dwSync03 )
	{
		sync3Start = fTime;		
		sync->dwSync03 = 0;
	}

	if( sync->dwSync04 )
	{
		sync4Start = fTime;		
		sync->dwSync04 = 0;
	}


	FLOAT coeff;

	BlurFace[0].sx = 0;
	BlurFace[1].sx = 640;
	BlurFace[2].sx = 0;
	BlurFace[3].sx = 640;
	BlurFace[0].sy = 0;
	BlurFace[1].sy = 0;
	BlurFace[2].sy = 480;
	BlurFace[3].sy = 480;

	if( fTime - sync1Start < 0.25f )
	{
		coeff = (fTime - sync1Start)*1600;

		BlurFace[0].sx = -coeff;
		BlurFace[1].sx = 640 + coeff;
		BlurFace[2].sx = -coeff;
		BlurFace[3].sx = 640 + coeff;
	}
	else
		if( fTime - sync1Start < 0.5f )
		{
			coeff = (fTime - sync1Start - 0.25)*1600;
			BlurFace[0].sx = coeff - 400;
			BlurFace[1].sx = 1040 - coeff;
			BlurFace[2].sx = coeff - 400;
			BlurFace[3].sx = 1040 - coeff;
		}
	
	
	if( fTime - sync2Start < 0.25f )
	{
		coeff = (fTime - sync2Start)*1600;

		BlurFace[0].sy = -coeff;
		BlurFace[1].sy = -coeff;
		BlurFace[2].sy = 480 + coeff;
		BlurFace[3].sy = 480 + coeff;
	}
	else
		if( fTime - sync2Start < 0.5 )
		{
			coeff = (fTime - sync2Start - 0.25)*1600;
			BlurFace[0].sy = coeff - 400;
			BlurFace[1].sy = coeff - 400;
			BlurFace[2].sy = 880 - coeff;
			BlurFace[3].sy = 880 - coeff;
		}
		

	if( fTime - sync0Start < 0.25f )
	{
		scale = 1.0f + 4*(fTime - sync0Start);
	}
	else
		if( fTime - sync0Start < 0.5f )
		{
			scale = 3.0f - 4*(fTime - sync0Start);
		}


	if( fTime - sync3Start < 0.5f )
	{
		speedup += (fTime - sync3Start)*0.2f;
	}	

	renderFlarez = 0;

	if( fTime - sync4Start < 1.0f )
	{
		renderFlarez = 1;
		//scale2 = 1.0f + fTime - sync4Start;
		DWORD alpha	= 255 - (DWORD)((fTime - sync4Start)*255.0f);

		Flare[0].dcColor = (alpha<<24)|0xffffff;
		Flare[1].dcColor = (alpha<<24)|0xffffff;
		Flare[2].dcColor = (alpha<<24)|0xffffff;
		Flare[3].dcColor = (alpha<<24)|0xffffff;
	}


	mtxFlarez = RotationMtx( fTimeKey, -fTimeKey, fTimeKey)*
				TranslationMtx( 0, 0, 20 );

	FLOAT		fKey = fTimeKey + speedup;

	mtxFlarez = ScaleMtx( scale2 )*
				RotationMtx( fKey, -fKey, fKey)*
				TranslationMtx( 0, 0, 20 );

	if( fTime < 4.0f )
	{
		matTentacles = (D3DMATRIX)( ScaleMtx( scale )*
								RotationMtx( fKey, -fKey, fKey)*
								TranslationMtx( 0, -80.0f + 20.0f*fTime, 20 ) );	
	}
	else
	{
		matTentacles = (D3DMATRIX)( ScaleMtx( scale )*
								RotationMtx( fKey, -fKey, fKey)*
								TranslationMtx( 0, 0, 20 ) );	
	}

	if( fTime < 4.0f )
	{
		DWORD		aph = (DWORD)(fTime*48.0f);
		aph <<= 24;

		BlurFace[0].dcColor = aph | 0xffffff;
		BlurFace[1].dcColor = aph | 0xffffff;
		BlurFace[2].dcColor = aph | 0xffffff;
		BlurFace[3].dcColor = aph | 0xffffff;
	}
	else
	{
		BlurFace[0].dcColor = 0xc0ffffff;
		BlurFace[1].dcColor = 0xc0ffffff;
		BlurFace[2].dcColor = 0xc0ffffff;
		BlurFace[3].dcColor = 0xc0ffffff;
	}

		
	for( i = 0 ; i < NUM_TENTACLES ; i++ )
	{
		FLOAT		s1 = 2*(sinf( (FLOAT)i*1.5f ) );
		FLOAT		s2 = 2*(cosf( (FLOAT)i*1.5f ) );
		FLOAT		s3 = 2*(sinf( (FLOAT)i*1.5f + G_PI*0.25f ) );		

		gem_Matrix	mtx1 = ScaleMtx( s3*( sin( s1*fKey ) ) )*
						   RotationMtx( s1*fKey, s2*fKey, s3*fKey );
		
		gem_Matrix	mtx2 = ScaleMtx( s2 *( cos( s3*fTimeKey ) ) )*
						   RotationMtx( s2*fKey, -s3*fKey, s1*fKey );		

		BE[i][1] = B[i][1]*mtx1;
		BE[i][2] = B[i][2]*mtx2;
		BE[i][3] = B[i][3]*ScaleMtx( 0.5f*s2*( cos( s1*fKey ) ) )*RotationMtx( -s3*fKey, s1*fKey, -s2*fKey );

		curTent = vertex[i];

		CreateTentacle( tentacles[i], BE[i], 1.0f );
	}	

	fTimeKey += 10;

	FLOAT	dir = 1;

	gem_Matrix	mtx;
	gem_Vector	vec[4], a[4];

	vec[0] = gem_Vector( Plate[0].x, Plate[0].y, Plate[0].z ); 
	vec[1] = gem_Vector( Plate[1].x, Plate[1].y, Plate[1].z ); 
	vec[2] = gem_Vector( Plate[2].x, Plate[2].y, Plate[2].z ); 
	vec[3] = gem_Vector( Plate[3].x, Plate[3].y, Plate[3].z ); 

	for( i = 0 ; i<300 ; i++, dir = -dir )
	{
		mtx = ScaleMtx( 1 + 0.5*sin( i ) )*
			  RotationMtx( 10, 0, dir*3*(3 + 2*sin((FLOAT)(2*i+1)))*fTimeKey )*
			  TranslationMtx( 0, 0, 300.0f - fmodf((2+cos(2*(FLOAT)(300 - i)))*fTimeKey*70, 320 ) );		

		a[0] = vec[0]*mtx;
		a[1] = vec[1]*mtx;
		a[2] = vec[2]*mtx;
		a[3] = vec[3]*mtx;

		PTunnel[i*4+0].x = a[0].x; PTunnel[i*4+0].y = a[0].y; PTunnel[i*4+0].z = a[0].z;
		PTunnel[i*4+1].x = a[1].x; PTunnel[i*4+1].y = a[1].y; PTunnel[i*4+1].z = a[1].z;
		PTunnel[i*4+2].x = a[2].x; PTunnel[i*4+2].y = a[2].y; PTunnel[i*4+2].z = a[2].z;
		PTunnel[i*4+3].x = a[3].x; PTunnel[i*4+3].y = a[3].y; PTunnel[i*4+3].z = a[3].z;		
	}

	if( fTime >= 31.0f )
	{
		renderSpiral = 1;
		FLOAT		size = (fTime - 31.0f)*120.0f + 10.0f;		

		for( i = 0 ; i < 100 ; i++ )
		{
			FLOAT		ang = 3.14159f*2.0f*(FLOAT)i/99.0f;

			Circle[i+1].sx = 320 + size*cosf( ang );
			Circle[i+1].sy = 240 + size*sinf( ang );
		}
	}

	if( fTime > 10.0f && fTime < 20.0f )
	{
		text1 = 1;
		tx1size = (fTime - 10.0f)*18.0f;
		text1_alpha = sinf( (fTime - 10.0f)*3.1415f*0.1f )*100.0f;
	}
	else
		text1 = 0;

	if( fTime > 17.0f && fTime < 26.0f )
	{
		text2 = 1;
		tx2size = (fTime - 17.0f)*10.0f;
		text2_alpha = sinf( (fTime - 17.0f)*3.1415f*0.111f )*150.0f;
	}
	else
		text2 = 0;

	return S_OK;
}

HRESULT fxRender_TentacleEfx( LPDIRECT3DDEVICE7 pd3dDevice )
{	
	DWORD					i, j;	

	LPDIRECTDRAWSURFACE7	target;
	HRESULT					hr;	
	D3DVIEWPORT7			viewPort;	

	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_WRAP0, FALSE ); 	

	pd3dDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, FALSE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_SHADEMODE, D3DSHADE_FLAT );  	

	D3DMATRIX		mat = (D3DMATRIX)IdentMtx();	

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

	pd3dDevice->BeginScene();

	pd3dDevice->SetRenderState( D3DRENDERSTATE_STENCILENABLE, FALSE );

	if( renderSpiral )
	{	
		pd3dDevice->SetTexture( 0, NULL );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, TRUE );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND,  D3DBLEND_ZERO );			
		pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE );		

		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,      0x5 );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_STENCILMASK,     0xffffffff );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_STENCILWRITEMASK,0xffffffff );
		
		pd3dDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, FALSE );		

		pd3dDevice->DrawPrimitive( D3DPT_TRIANGLEFAN, D3DFVF_TLVERTEX, Circle, 101, 0 );

		pd3dDevice->SetRenderState( D3DRENDERSTATE_STENCILFUNC,  D3DCMP_NOTEQUAL );

		pd3dDevice->SetRenderState( D3DRENDERSTATE_STENCILZFAIL, D3DSTENCILOP_KEEP );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_STENCILFAIL,  D3DSTENCILOP_KEEP );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_STENCILPASS,  D3DSTENCILOP_KEEP );		
	}

	pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND,  D3DBLEND_ONE );			
	pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE );	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ZENABLE, D3DZB_USEW );	
	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, TRUE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, FALSE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_NONE );	
	pd3dDevice->SetTexture( 0, GetTexture( "data\\textures\\toonel.jpg" ) );
	pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &mat );	

	pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, D3DFVF_LVERTEX, PTunnel, 1200, 
								      PTunnelInd, 1800, 0 );				

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

	pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &matTentacles );	
	pd3dDevice->SetTexture( 0, GetTexture( "data\\textures\\tent.jpg" ) );	

	for( i = 0 ; i < NUM_TENTACLES ; i++ )
		pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, D3DFVF_VERTEX, tentacles[i], 600, 0 );			

	pd3dDevice->SetTexture( 0, GetTexture( "data\\textures\\part.jpg" ) );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND,  D3DBLEND_SRCALPHA );			
	pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE );	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, TRUE );	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, FALSE );	
	pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );

	if( renderFlarez )
	{
		for( i = 0 ; i < NUM_TENTACLES ; i++ )
			for( j = 0 ; j < 100 ; j+=2 )
			{
				mat = (D3DMATRIX)TranslationMtx( vertex[i][j]*mtxFlarez );
				pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &mat );
				pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, Flare, 4, 0 );
			}
	}

	//pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, FALSE );
	pd3dDevice->SetTexture( 0, text[blurpage] );		
	pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND,  D3DBLEND_SRCALPHA );			
	pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA );		
	hr = pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, D3DFVF_TLVERTEX, BlurFace, 4, 0 );
	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->SetTexture( 0, GetTexture( "data\\textures\\fg_Tentacle.jpg" ) );	
	pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, D3DFVF_TLVERTEX, Overground, 4, 0 );

	if( text1 )
		RenderEfxFace( 340, 150, 504 + tx1size, 114 + tx1size, text1_alpha, GetTexture( "data\\texts\\napis_11.jpg" ), pd3dDevice );

	if( text2 )
		RenderEfxFace( 450, 300, 319 + tx2size, 141 + tx2size, text2_alpha, GetTexture( "data\\texts\\napis_7.jpg" ), pd3dDevice );
	
	pd3dDevice->SetTexture( 0, NULL );	
	
	pd3dDevice->EndScene();

	if( !renderSpiral )
	{	
		hr = pd3dDevice->GetViewport( &viewPort );
		hr = pd3dDevice->GetRenderTarget( &target );
		hr = pd3dDevice->SetRenderTarget( text[(blurpage + 1)%2], 0 );
		hr = pd3dDevice->SetViewport( &view );
		hr = pd3dDevice->Clear( 1UL, NULL, D3DCLEAR_TARGET|D3DCLEAR_ZBUFFER, 0x00000000, 1.0f, 0L );	

		mat = (D3DMATRIX)IdentMtx();

		hr = pd3dDevice->BeginScene();	

		pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND,  D3DBLEND_ONE );			
		pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE );	
		pd3dDevice->SetRenderState( D3DRENDERSTATE_ZENABLE, D3DZB_USEW );	
		
		pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, TRUE );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, FALSE );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_NONE );	
		pd3dDevice->SetTexture( 0, GetTexture( "data\\textures\\toonel.jpg" ) );
		pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &mat );	

		pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, D3DFVF_LVERTEX, PTunnel, 1200, 
									      PTunnelInd, 1800, 0 );				

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

		pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &matTentacles );	
		pd3dDevice->SetTexture( 0, GetTexture( "data\\textures\\tent.jpg" ) );	

		for( i = 0 ; i < NUM_TENTACLES ; i++ )
			pd3dDevice->DrawPrimitive( D3DPT_TRIANGLELIST, D3DFVF_VERTEX, tentacles[i], 600, 0 );			

		pd3dDevice->SetTexture( 0, GetTexture( "data\\textures\\part.jpg" ) );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND,  D3DBLEND_SRCALPHA );			
		pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE );	
		pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, TRUE );	
		pd3dDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, FALSE );	
		pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );

		if( renderFlarez )
		{
			for( i = 0 ; i < NUM_TENTACLES ; i++ )
				for( j = 0 ; j < 100 ; j+=2 )
				{
					mat = (D3DMATRIX)TranslationMtx( vertex[i][j]*mtxFlarez );
					pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &mat );
					pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, D3DFVF_LVERTEX, Flare, 4, 0 );
				}
		}
		
		pd3dDevice->SetTexture( 0, text[blurpage] );		
		pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND,  D3DBLEND_SRCALPHA );			
		pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA );		
		pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, D3DFVF_TLVERTEX, BlurFace2, 4, 0 );
		pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );

		pd3dDevice->SetTexture( 0, NULL );		

		hr = pd3dDevice->EndScene();

		hr = pd3dDevice->SetRenderTarget( target, 0 );
		hr = pd3dDevice->SetViewport( &viewPort );
		target->Release();

		blurpage = (blurpage + 1)%2;
	}

	return S_OK;
}

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

VOID fxDelete_TentacleEfx( LPDIRECT3DDEVICE7 pd3dDevice )
{
	SAFE_RELEASE( text[0] );
	SAFE_RELEASE( text[1] );
	SAFE_RELEASE( zbuffer1 );
	SAFE_RELEASE( zbuffer2 );
}


