//------------------------------------------------------------------------------------------
// weird tunnel efect with volumetric light
// by acid/z51
//------------------------------------------------------------------------------------------
// this file is part of source code from entropy! demo (c)zone51 `2000
//------------------------------------------------------------------------------------------

#define	 D3D_OVERLOADS
#include <math.h>
#include "volumetric.h"
#include "texture.h"
#include "TunnelEfx.h"
#include "extrastuff.h"
#include "texturemenager.h"


// global variables declaration such as object, textures, etc, easier to manipulate since
// they are global

//	matrices

static	DWORD					Draw2ndTunnel = 0;
static	D3DLVERTEX				Plate[4];
static	D3DLVERTEX				PTunnel[1200];					// tunnel faces
static	WORD					PTunnelInd[1800];

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


static	D3DMATRIX				g_matMorph;
static	D3DMATRIX				g_matLocal;
static	D3DMATRIX				matObjProj;
static	D3DMATRIX				g_matObject1;
static	D3DMATRIX				g_matObject2;
static	gem_Matrix				mtxVertexTrn;

// volumes 
static	VOLUMEINFO				vInfo;
static	VOLUME					volume;

// objects
static	OBJECT3D				torus[5];
static	OBJECT3D				blob[2];
static	OBJECT3D				morph1, morph2;
static	OBJECT3D				morphed;
static	OBJECT3D				sphere;

static	D3DVERTEX				shapes[5][48];
static	D3DVERTEX				mshape[48];

// other stuff
static	D3DLVERTEX				Flare[4];

static	LPWORD					pLineBlobInd	= NULL;
static	DWORD					dwLineBlobIndNbr;

static	DWORD					lightOff[6];
static	DWORD					lineOn1;
static	DWORD					lineOn2;

static	FLOAT					alpha1;
static	FLOAT					alpha2;

static	D3DMATERIAL7			mtrlAlpha;

static	D3DTLVERTEX				Overground[4];

#define	SEGCOUNT	15
#define	SEGSIDES	48
#define	SEGLEN		45.0f

// tunnel
static	D3DVERTEX				tunnel[SEGCOUNT*SEGSIDES*2];
static	WORD					tunnelInd[(SEGCOUNT-1)*SEGSIDES*12];
static	WORD					curSection = 0;
static	FLOAT					ZPos = 0;
static	FLOAT					tunnelend = (SEGCOUNT-1)*SEGLEN;

//extra stuff

static	LPDIRECTDRAWSURFACE7	mask = NULL;
static	D3DTLVERTEX				maskFace[4];
static	DWORD					renderMask = 0;
static	FLOAT					vpx, vpy;
static	DWORD					stencil2clear;

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

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


#define		CreateFace( IndTable, i1, i2, i3 ) (*(IndTable)++ = (WORD)(i1),\
											    *(IndTable)++ = (WORD)(i2),\
											    *(IndTable)++ = (WORD)(i3))

// just create tunnel indices table, nothing more nothing less
VOID CreateTunnel( LPWORD ind, WORD segCount, WORD segSides )
{
	LPWORD		indtab = ind;
	WORD		ii;

	for( int i = 0; i<segCount-1 ; i++ )
	{
		for( int j = 0; j<segSides-1 ; j++ )
		{
			ii = 2*i*segSides + j;
			CreateFace( indtab, ii, ii+segSides+1, ii+1 );
			CreateFace( indtab, ii, ii+segSides, ii+segSides+1);
		}

		ii = 2*i*segSides + segSides-1;

		CreateFace( indtab, ii, (2*i+1)*segSides, 2*i*segSides );
		CreateFace( indtab, ii, ii+segSides, (2*i+1)*segSides );
	}
}		

VOID WriteTunnel( LPD3DVERTEX tunnel, LPD3DVERTEX shape, WORD segSides, FLOAT z, WORD count = 1, WORD start = 0, FLOAT seglen = SEGLEN )
{
	D3DVERTEX			a;
	FLOAT				curTU;
	gem_Vector			off1, off2;

	for( int i = start ; i<(start+count) ; i++, z+=seglen )
	{
		curTU = (FLOAT)(i%5)*0.2f;
		
		off1.x = 20*sinf( z*0.01f );
		off1.y = 15*sinf( z*0.01f )*cosf( z*0.02f );
		off1.z = z;
		off2.x = 20*sinf( (z + seglen)*0.01f );
		off2.y = 15*sinf( (z + seglen)*0.01f )*cosf( (z + seglen)*0.02f );
		off2.z = z + seglen;

		for( int j = 0 ; j<segSides ; j++ )
		{		
			a = shape[j];
			a.x += off1.x;
			a.y += off1.y;
			a.z = off1.z;
			tunnel[2*i*segSides+j] = a;
			tunnel[2*i*segSides+j].tu = curTU;

			a = shape[j];
			a.x += off2.x;
			a.y += off2.y;
			a.z = off2.z;
			tunnel[(2*i+1)*segSides+j] = a;
			tunnel[(2*i+1)*segSides+j].tu = curTU + 0.2f;
		}
	}
}
 
VOID ChangeTunnelShape( LPD3DVERTEX tunnel, LPD3DVERTEX shape, WORD segCount, WORD segSides )
{
	gem_Vector		off;
	FLOAT			z;

	for( int i = 0 ; i<segCount*2 ; i++ )
	{
		z = tunnel[i*segSides].z;
		off.x = 20*sinf( z*0.01f );
		off.y = 15*cosf( z*0.02f );

		for( int j = 0 ; j<segSides ; j++ )
		{
			tunnel[i*segSides+j].x = shape[j].x + off.x;
			tunnel[i*segSides+j].y = shape[j].y + off.y;
		}
	}
}


// initialization, loads object textures etc.
HRESULT	fxInit_Tunnel( LPDIRECT3DDEVICE7 pd3dDevice )
{	
	LoadAlphaChannel( "data\\textures\\move2.bmp", &mask, pd3dDevice );

	LPDIRECTDRAWSURFACE7	surf;

	LoadTexture( "data\\textures\\alien2.jpg", pd3dDevice );	
	LoadTexture( "data\\textures\\texturka.jpg", pd3dDevice );
	LoadTexture( "data\\textures\\efxtex.jpg", pd3dDevice );	
	LoadTexture( "data\\textures\\light2.jpg", pd3dDevice );
	LoadTexture( "data\\textures\\volume.jpg", pd3dDevice );
	LoadTexture( "data\\textures\\innertun.jpg", pd3dDevice );
	LoadTexture( "data\\textures\\toonel.jpg", pd3dDevice );	
	LoadTexture( "data\\textures\\fg_Tunnel.jpg", pd3dDevice );	
	LoadTexture( "data\\texts\\napis_9.jpg", pd3dDevice );
	LoadTexture( "data\\texts\\napis_3.jpg", pd3dDevice );	

	surf = GetTexture( "data\\textures\\texturka.jpg" );
	LoadAlphaChannel( "data\\textures\\alpha3.bmp", &surf, pd3dDevice, 0 );

	surf = GetTexture( "data\\textures\\fg_Tunnel.jpg" );
	LoadAlphaChannel( "data\\textures\\fg_Tunnel_alpha.bmp", &surf, pd3dDevice, 0 );
    
	vInfo.chull = new gem_Vector[10];
	vInfo.vNbr  = 10;
	vInfo.emiterPos = gem_Vector( 0, 0, -3 );

	LONG		i, j;

	volume.iNbrHull = 0;
	volume.vNbrHull = 0;
	volume.vNbrSpot = 0;

	for( i = 0 ; i<10 ; i++ )
	{
		FLOAT	ang = 3.14159f*(FLOAT)i/5.0f;

		vInfo.chull[i].x = 0.6f*(FLOAT)cos( ang );
		vInfo.chull[i].y = 0.6f*(FLOAT)sin( ang );
		vInfo.chull[i].z = 4.02f;
	}	

	LoadObject3D( "data\\objects\\disco.o3d", &sphere );

	gem_Vector	center( 0, 0, 0 );

	for( i = 0 ; i < sphere.vertNbr ; i++ )
	{
		center.x += sphere.vert[i].x;
		center.y += sphere.vert[i].y;
		center.z += sphere.vert[i].z;
	}

	center.x /= (FLOAT)sphere.vertNbr;
	center.y /= (FLOAT)sphere.vertNbr;
	center.z /= (FLOAT)sphere.vertNbr;

	gem_Matrix	mtxx = TranslationMtx( -center )*ScaleMtx( 0.4f );

	TransformObject3D( &sphere, mtxx );


	ApplySphereMap( sphere.vert, sphere.vertNbr, pd3dDevice );	
	
	LoadObject3D( "data\\objects\\tor01.o3d", &morphed );	

	LoadObject3D( "data\\objects\\tor00.o3d", &torus[0] );
	LoadObject3D( "data\\objects\\tor01.o3d", &torus[1] );
	LoadObject3D( "data\\objects\\tor02.o3d", &torus[2] );
	LoadObject3D( "data\\objects\\tor03.o3d", &torus[3] );	
	LoadObject3D( "data\\objects\\tor04.o3d", &torus[4] );

	for( i = 0 ; i<5 ; i++ )
	{
		gem_Vector		a( 0, 0, 0 );		

		for( j = 0 ; j<48 ; j++ )
		{
			shapes[i][j] = torus[i].vert[j];
			shapes[i][j].x = torus[i].vert[j].z;
			shapes[i][j].z = torus[i].vert[j].x;
			a.x += shapes[i][j].x;
			a.y += shapes[i][j].y;
			a.z += shapes[i][j].z;
		}

		a.x /= 48.0f; a.y /= 48.0f; a.z /= 48.0f;
		
		for( j = 0 ; j<48 ; j++ )
		{
			shapes[i][j].x -= a.x;
			shapes[i][j].y -= a.y;
			shapes[i][j].z -= a.z;
		}
	}

	CreateTunnel( tunnelInd, SEGCOUNT, SEGSIDES );
	WriteTunnel( tunnel, shapes[0], SEGSIDES, 0, SEGCOUNT );
	
	LoadObject3D( "data\\objects\\blob01.o3d", &blob[0] );	
	LoadObject3D( "data\\objects\\blob02.o3d", &blob[1] );
	LoadObject3D( "data\\objects\\blob02.o3d", &morph1 );
	LoadObject3D( "data\\objects\\blob01.o3d", &morph2 );

	CreateLineList( &blob[0], dwLineBlobIndNbr, pLineBlobInd );	

	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 );

	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];
	}	

	D3DVECTOR vFar = D3DVECTOR( 0.0f, 0.0f, 0.5f );
    FadeV[0] = D3DTLVERTEX( vFar, 0.5f, 0x0, 0, 0.0f, 1.0f );
    FadeV[1] = D3DTLVERTEX( vFar, 0.5f, 0x0, 0, 0.0f, 0.0f );
    FadeV[2] = D3DTLVERTEX( vFar, 0.5f, 0x0, 0, 1.0f, 1.0f );
    FadeV[3] = D3DTLVERTEX( vFar, 0.5f, 0x0, 0, 1.0f, 0.0f );

	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 );	

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

	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;

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


// animation and sync
HRESULT fxFrameMove_Tunnel( LPDIRECT3DDEVICE7 pd3dDevice, LPSYNCINFO sync )
{	
	//************************************************************************

	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	= 10.0f;
	light.dvPosition.y	= 0.0f;
	light.dvPosition.z	= 40.0f;
	light.dvAttenuation0= 1.0f;
	light.dvAttenuation1= 0.02f;
	light.dvAttenuation2= 0.0002f;
	light.dvRange		= 40.0f;

	pd3dDevice->SetLight( 0, &light );
	
	pd3dDevice->LightEnable( 0, TRUE );

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

	ZeroMemory( &mtrlAlpha, sizeof(mtrlAlpha) );
    mtrlAlpha.dcvAmbient.r = 1.0f;
    mtrlAlpha.dcvAmbient.g = 1.0f;
    mtrlAlpha.dcvAmbient.b = 1.0f;
	mtrlAlpha.dcvDiffuse.r = 0.0f;
    mtrlAlpha.dcvDiffuse.g = 0.0f;
    mtrlAlpha.dcvDiffuse.b = 0.0f;
	mtrlAlpha.dcvDiffuse.a = 0.2f;		

	Flare[0] = D3DLVERTEX( D3DVECTOR(-3, 3, 0 ), 0x80ffffff, 0, 0, 0 );
	Flare[1] = D3DLVERTEX( D3DVECTOR( 3, 3, 0 ), 0x80ffffff, 0, 1, 0 );
	Flare[2] = D3DLVERTEX( D3DVECTOR(-3,-3, 0 ), 0x80ffffff, 0, 0, 1 );
	Flare[3] = D3DLVERTEX( D3DVECTOR( 3,-3, 0 ), 0x80ffffff, 0, 1, 1 );
	
	D3DMATRIX matView = (D3DMATRIX)CameraMtx( gem_Vector( 0, 0, -10 ), gem_Vector( 0, 0, 10 ), 0 );	
    pd3dDevice->SetTransform( D3DTRANSFORMSTATE_VIEW, &matView );
	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_AMBIENT, 0xFFFFFFFF );
//***********************************************************************************************


	LONG	i;
	FLOAT	coeff;
	FLOAT	fTimeKey = sync->fTimeKey;

	static  FLOAT sync0Key;
	static	DWORD dwSync0;
	static  FLOAT sync1Key;
	static	DWORD dwSync1;
	
	static  FLOAT lightOffTime[6];

	static  D3DMATRIX matProj;

	static  FLOAT lineOn1Key;
	static  FLOAT lineOn2Key;	

	gem_Vector campos;
	gem_Vector camtrg;
	gem_Vector volpos;

	ZPos = fTimeKey*150.0f;
	campos = gem_Vector( 20*sinf( ZPos*0.01f), 15*cosf( ZPos*0.02f ), ZPos );
	camtrg = gem_Vector( 20*sinf( (ZPos+50)*0.01f), 15*cosf( (ZPos+50)*0.02f ), ZPos+50 );
	volpos = gem_Vector( 20*sinf( (ZPos+80 + 10*sinf( fTimeKey*0.5f ) )*0.01f ),
						 15*cosf( (ZPos+80 + 10*sinf( fTimeKey*0.5f ) )*0.02f ),
						 ZPos + 80 + 10*sinf( fTimeKey ) );						

	

	if( fTimeKey>2.0f && fTimeKey<2.5f )
	{
		DeleteVolume( &volume );
		CreateVolume( &vInfo, &volume, (fTimeKey - 2.0f)*100.0f );		
	}

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

	if( dwSync0 )
	{		
		
		if( fTimeKey - sync0Key < 0.2f )
		{
			coeff = (fTimeKey - sync0Key)*5.0f;
			matProj = (D3DMATRIX)ProjectionMtx( 50.0f + 100*coeff, 1.0f, 1000.0f, 0.70f );			
		}
		else
		{
			dwSync0 = 0;
			sync0Key = fTimeKey;
			matProj = (D3DMATRIX)ProjectionMtx( 150.0f, 1.0f, 1000.0f, 0.70f );			
		}

	}
	else
	{
		if( fTimeKey - sync0Key < 0.5f )
		{
			coeff = (fTimeKey - sync0Key)*2.0f;
			matProj = (D3DMATRIX)ProjectionMtx( 150.0f - 100*coeff, 1.0f, 1000.0f, 0.70f );			
		}
		else
		{
			matProj = (D3DMATRIX)ProjectionMtx( 50.0f, 1.0f, 1000.0f, 0.70f );
		}
	}

	matObjProj = (D3DMATRIX)ProjectionMtx( 50.0f, 1.0f, 1000.0f, 0.70f );			
	
    pd3dDevice->SetTransform( D3DTRANSFORMSTATE_PROJECTION, &matProj );

	for( i = 2 ; i<8 ; i++ )
	{
		if( sync->tableSync[i] )
		{
			lightOff[i-2] = 1;
			sync->tableSync[i] = 0;
			lightOffTime[i-2] = fTimeKey;
		}
	}

	for( i = 0 ; i<6 ; i++ )
	{
		if( lightOff[i] )
		{
			if( fTimeKey - lightOffTime[i] > 0.2f )
			{			
				lightOff[i] = 0;								
			}		
		}
	}

	if( sync->dwSync08 )
	{
		lineOn1 = 1;
		sync->dwSync08 = 0;
		lineOn1Key = fTimeKey;
	}

	if( lineOn1 )
	{
		if( fTimeKey - lineOn1Key <= 0.5f )
		{
			alpha1 = 0.25f - 0.5f*( fTimeKey - lineOn1Key );
		}
		else
		{
			lineOn1 = 0;
		}		
	}

	if( sync->dwSync09 )
	{
		lineOn2 = 1;
		sync->dwSync09 = 0;
		lineOn2Key = fTimeKey;
	}

	if( lineOn2 )
	{
		if( fTimeKey - lineOn2Key <= 0.5f )
		{
			alpha2 = 0.25f - 0.5f*( fTimeKey - lineOn2Key );
		}
		else
		{
			lineOn2 = 0;
		}		
	}

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

	
	if( dwSync1 )
	{
		if( fTimeKey - sync1Key < 0.5f )
		{
			coeff = (fTimeKey - sync1Key)*2.0f;
			g_matLocal = (D3DMATRIX)(RotationMtx( -0.6f*fTimeKey, 1.05f*fTimeKey, -0.85f*fTimeKey )*
									 TranslationMtx( volpos.x + 10.0f, volpos.y, volpos.z - 20.0f - 30.0f*coeff ));
		}
		else
		{
			dwSync1 = 0;
			sync1Key = fTimeKey;
			g_matLocal = (D3DMATRIX)(RotationMtx( -0.6f*fTimeKey, 1.05f*fTimeKey, -0.85f*fTimeKey )*
								     TranslationMtx( volpos.x + 10.0f, volpos.y, volpos.z - 50.0f));
		}
	}
	else
	{
		if( fTimeKey - sync1Key < 0.2f )
		{
			coeff = (fTimeKey - sync1Key)*5.0f;
			g_matLocal = (D3DMATRIX)(RotationMtx( -0.6f*fTimeKey, 1.05f*fTimeKey, -0.85f*fTimeKey )*
									 TranslationMtx( volpos.x + 10.0f, volpos.y, volpos.z - 50.0f + coeff*30.0f ));
		}
		else
		{
			g_matLocal = (D3DMATRIX)(RotationMtx( -0.6f*fTimeKey, 1.05f*fTimeKey, -0.85f*fTimeKey )*
								     TranslationMtx( volpos.x + 10.0f, volpos.y, volpos.z - 20.0f ));
		}
	}	

	mtxVertexTrn = ScaleMtx( 0.8f )*(RotationMtx( -0.5f*fTimeKey, 0, 0 )*TranslationMtx( 64, 0, 40 ));	

	if( fTimeKey<2.0f )
	{
		g_matObject1= (D3DMATRIX)(RotationMtx( -1.5f*fTimeKey, 1.5f*fTimeKey, -fTimeKey )*
							      TranslationMtx( -80, -1, 20 ));
		
		g_matObject2= (D3DMATRIX)(RotationMtx( fTimeKey, -1.5f*fTimeKey, 1.5f*fTimeKey )*
							      TranslationMtx( -80, -1, 20 ));
	}
	else
	{
		if( fTimeKey<4.0f )
		{
			coeff = (fTimeKey - 2.0f)*0.5f;
			g_matObject1= (D3DMATRIX)(RotationMtx( -1.5f*fTimeKey, 1.5f*fTimeKey, -fTimeKey )*
							          TranslationMtx( -30 + 22*coeff, -1, 20 ));

			g_matObject2= (D3DMATRIX)(RotationMtx( fTimeKey, -1.5f*fTimeKey, 1.5f*fTimeKey )*
							          TranslationMtx( -30 + 22*coeff, -1, 20 ));
		}
		else
		{
			g_matObject1= (D3DMATRIX)(RotationMtx( -1.5f*fTimeKey, 1.5f*fTimeKey, -fTimeKey )*
							          TranslationMtx( -8, -1, 20 ));

			g_matObject2= (D3DMATRIX)(RotationMtx( fTimeKey, -1.5f*fTimeKey, 1.5f*fTimeKey )*
						 			  TranslationMtx( -8, -1, 20 ));
		}
	}

	if( fTimeKey > 34.0f )
	{
		g_matObject1= (D3DMATRIX)(RotationMtx( -1.5f*fTimeKey, 1.5f*fTimeKey, -fTimeKey )*
							      TranslationMtx( -8 + 15.0f*(fTimeKey - 34.0f), -1, 20 ));

		g_matObject2= (D3DMATRIX)(RotationMtx( fTimeKey, -1.5f*fTimeKey, 1.5f*fTimeKey )*
						 		  TranslationMtx( -8, -1 + 20.0f*(fTimeKey-34.0f), 20 ));
	}

	LONG		frame = (LONG)(fTimeKey*250.0f);
	LONG		srcInd, src2;
	LONG		destInd, dest2;
	FLOAT		mFactor;
	
	frame = frame%800;

	if( frame>=0 && frame<200 )
	{
		mFactor = (FLOAT)frame*0.005f;
		srcInd = 4;
		destInd = 3;	
		src2 = 1;
		dest2 = 2;
	}

	if( frame>=200 && frame<400 )
	{
		mFactor = (FLOAT)(frame-200)*0.005f;
		srcInd = 3;
		destInd = 1;	

		src2 = 2;
		dest2 = 3;
	}

	if( frame>=400 && frame<600 )
	{
		mFactor = (FLOAT)(frame-400)*0.005f;
		srcInd = 1;
		destInd = 2;	

		src2 = 3;
		dest2 = 4;
	}

	if( frame>=600 && frame<800 )
	{
		mFactor = (FLOAT)(frame-600)*0.005f;
		srcInd = 2;
		destInd = 4;	

		src2 = 4;
		dest2 = 1;
	}	
	
	for( i = 0 ; i<48 ; i++ )
	{
		mshape[i] = vLERP( shapes[srcInd][i], shapes[destInd][i], mFactor );
		mshape[i].x *= 1.65f;
		mshape[i].y *= 1.15f;
	}

	DWORD	tmp = (DWORD)floor(ZPos/SEGLEN); tmp %= (SEGCOUNT-1); 
	if( tmp != curSection )
	{
		WriteTunnel( tunnel, shapes[0], 48, tunnelend, 1, curSection );
		tunnelend += SEGLEN;
		curSection = tmp;
	}

	g_matMorph = (D3DMATRIX)CameraMtx( campos, camtrg, ZPos*0.01f*30 );	

	ChangeTunnelShape( tunnel, mshape, SEGCOUNT, SEGSIDES );

	for( i = 0 ; i<48 ; i++ )
	{
		mshape[i].x *= 0.5f;
		mshape[i].y *= 0.5f;
	}
		
	coeff = (1.0f + (FLOAT)sin( fTimeKey ))*0.5f;

	MorphObject( &blob[0], &blob[1], coeff, &morph1 );	
	MorphObject( &blob[1], &blob[0], coeff, &morph2 );	

	if( fTimeKey > 32.0f )
	{	
		Draw2ndTunnel = 1;

		FLOAT	dir = 1;
		FLOAT	fTime = (fTimeKey - 32.0f)*0.1f + 9.0f;

		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.5f*sinf( (FLOAT)i ) )*
				  RotationMtx( 10, 0, dir*3*(3 + 2*sinf((FLOAT)(2*i+1)))*fTime )*
				  TranslationMtx( 0, 0, 300.0f - fmodf((2+cosf(2*(FLOAT)(300 - i)))*fTime*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;		
		}

		DWORD	col = (fTimeKey-32.0f)*0.25*255.0f;

		if( col > 255 )
			col = 255;

		col <<= 24;
		col |=  0xffffff;

		SetColorValue( PTunnel, 1200, col );			
	}

	if( fTimeKey > 35.0f )
	{
		Fade = 1;

		DWORD alpha = (DWORD)( ( fTimeKey-35.0f )*0.333f*255.0f );

		if( alpha > 255 ) 
		{
			alpha = 255;			
		}

		alpha <<= 24;

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

		Overground[0].dcColor = ~alpha;
		Overground[1].dcColor = ~alpha;
		Overground[2].dcColor = ~alpha;
		Overground[3].dcColor = ~alpha;
	}

	if( fTimeKey < 3.0f )
	{
		renderMask = 1;

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

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

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

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

	}
	else
	{
		if( stencil2clear )
		{		
			pd3dDevice->Clear( 1UL, NULL, D3DCLEAR_STENCIL, 0x0, 1.0f, 0 );		
			stencil2clear = 0;
		}

		renderMask = 0;
	}

	if( fTimeKey > 12.0f && fTimeKey < 20.0f )
	{
		text1 = 1;
		tx1size = (fTimeKey - 12.0f)*20.0f;
		text1_alpha = sinf( (fTimeKey - 12.0f)*3.1415f*0.125f )*200.0f;
	}
	else
		text1 = 0;


	if( fTimeKey > 18.0f && fTimeKey < 28.0f )
	{
		text2 = 1;
		tx2posx = (fTimeKey - 18.0f)*20.0f;
		text2_alpha = sinf( (fTimeKey - 18.0f)*3.1415f*0.1f )*200.0f;
	}
	else
		text2 = 0;


	return S_OK;
}

// rendering
HRESULT fxRender_Tunnel( LPDIRECT3DDEVICE7 pd3dDevice )
{	
	D3DMATRIX				mat = (D3DMATRIX)IdentMtx();		

	pd3dDevice->Clear( 1UL, NULL, D3DCLEAR_ZBUFFER, 0x0, 1.0f, 0 );		

	pd3dDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, FALSE );
	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_ZENABLE, D3DZB_USEW );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, TRUE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, FALSE );	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_WRAP0, D3DWRAPCOORD_0 | D3DWRAPCOORD_1 ); 	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_STENCILENABLE, FALSE );

	if( renderMask )
	{
		pd3dDevice->SetRenderState( D3DRENDERSTATE_STENCILENABLE, TRUE );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_STENCILFUNC,   D3DCMP_EQUAL );

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

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

	pd3dDevice->SetTransform( D3DTRANSFORMSTATE_VIEW, &g_matMorph );

	pd3dDevice->SetTexture( 0,  GetTexture( "data\\textures\\efxtex.jpg" ) );	
	pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &g_matLocal );	
	ApplySphereMap( sphere.vert, sphere.vertNbr, pd3dDevice );	
	RenderObject3D( &sphere, pd3dDevice );	

	pd3dDevice->SetTexture( 0, GetTexture( "data\\textures\\alien2.jpg" ) );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_NONE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, TRUE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ZENABLE, D3DZB_USEW );		
	
	pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &mat );	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_NONE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, FALSE );			
	pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, D3DFVF_VERTEX, 
									  tunnel, SEGCOUNT*SEGSIDES*2, tunnelInd, (SEGCOUNT-1)*SEGSIDES*12, 0 );

	ChangeTunnelShape( tunnel, mshape, SEGCOUNT, SEGSIDES );

	pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, TRUE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE);
	pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, FALSE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, TRUE );

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

	pd3dDevice->DrawIndexedPrimitive( D3DPT_TRIANGLELIST, D3DFVF_VERTEX, 
									  tunnel, SEGCOUNT*SEGSIDES*2, tunnelInd, (SEGCOUNT-1)*SEGSIDES*12, 0 );

	gem_Vector a;
	D3DMATRIX  flareMat;	

	pd3dDevice->SetTexture( 0, GetTexture( "data\\textures\\light2.jpg" ) );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_WRAP0, FALSE ); 	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, FALSE );		
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, TRUE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND, D3DBLEND_ONE);
	pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_NONE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ZWRITEENABLE, FALSE );	

	for( LONG z = 0 ;  z<SEGCOUNT ; z+=3 )
	{
		for( LONG k = z*2*SEGSIDES ; k<SEGSIDES*(2*z+1) ; k++ )
		{
			a.x = tunnel[k].x;
			a.y = tunnel[k].y;
			a.z = tunnel[k].z;

			flareMat = (D3DMATRIX)TranslationMtx( a );
			pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &flareMat );	

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

	pd3dDevice->SetRenderState( D3DRENDERSTATE_WRAP0, D3DWRAPCOORD_0 | D3DWRAPCOORD_1 ); 	

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

	for( LONG i = 0 ; i<4; i++ )
	{				
		if( !lightOff[i] )
		{			
		
			mat = (D3DMATRIX)RotationMtx( (FLOAT)i*0.5f*3.14159f, 0, 0 )*g_matLocal;
			pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &mat );
			RenderVolume( &volume, GetTexture( "data\\textures\\volume.jpg" ), pd3dDevice );			
		}
	}

		
	if( !lightOff[4] )
	{
		mat = GetD3DMATRIX( RotationMtx( 0, 0.5f*3.14159f, 0 ) )*g_matLocal;
		pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &mat );
		RenderVolume( &volume, GetTexture( "data\\textures\\volume.jpg" ),  pd3dDevice );		
	}


	if( !lightOff[5] )
	{
		mat = GetD3DMATRIX( RotationMtx( 0, -0.5f*3.14159f, 0 ) )*g_matLocal;
		pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &mat );
		RenderVolume( &volume, GetTexture( "data\\textures\\volume.jpg" ), pd3dDevice );		
	}

	D3DMATRIX matView = (D3DMATRIX)CameraMtx( gem_Vector( 0, 0, -10 ), gem_Vector( 0, 0, 10 ), 0 );	
    pd3dDevice->SetTransform( D3DTRANSFORMSTATE_VIEW, &matView );

	pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );

	pd3dDevice->SetTexture( 0, GetTexture( "data\\textures\\texturka.jpg" ) );	
	pd3dDevice->SetTransform( D3DTRANSFORMSTATE_PROJECTION, &matObjProj );
	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ZENABLE, FALSE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_ALPHABLENDENABLE, TRUE );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_CULLMODE, D3DCULL_NONE );	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND, D3DBLEND_SRCALPHA );
	pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_ONE );	

	pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &g_matObject1 );
	ApplySphereMap( morph1.vert, morph1.vertNbr, pd3dDevice );
	RenderObject3D( &morph1, pd3dDevice );

	if( lineOn1 )
	{
		D3DMATERIAL7		mtrl;		
		D3DMATRIX			matLine = (D3DMATRIX)ScaleMtx( alpha1*2.0f + 1.0f)*g_matObject1;

		pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &matLine );

		mtrlAlpha.dcvDiffuse.a = alpha1;

		pd3dDevice->GetMaterial( &mtrl );
		pd3dDevice->SetMaterial( &mtrlAlpha );

		pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, TRUE );		

		pd3dDevice->DrawIndexedPrimitive( D3DPT_LINELIST, D3DFVF_VERTEX, 
										  morph1.vert, morph1.vertNbr, 
										  pLineBlobInd, dwLineBlobIndNbr, NULL );

		pd3dDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, FALSE );		
		pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
		pd3dDevice->SetMaterial( &mtrl );
	}
	
	pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &g_matObject2 );
	ApplySphereMap( morph2.vert, morph2.vertNbr, pd3dDevice );
	RenderObject3D( &morph2, pd3dDevice );	

	if( lineOn2 )
	{
		D3DMATERIAL7		mtrl;		
		D3DMATRIX			matLine = (D3DMATRIX)ScaleMtx( alpha2*2.0f + 1.0f)*g_matObject2;

		pd3dDevice->SetTransform( D3DTRANSFORMSTATE_WORLD, &matLine );

		mtrlAlpha.dcvDiffuse.a = alpha2;

		pd3dDevice->GetMaterial( &mtrl );
		pd3dDevice->SetMaterial( &mtrlAlpha );

		pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, TRUE );				

		pd3dDevice->DrawIndexedPrimitive( D3DPT_LINELIST, D3DFVF_VERTEX, 
										  morph2.vert, morph2.vertNbr, 
										  pLineBlobInd, dwLineBlobIndNbr, NULL );

		pd3dDevice->SetRenderState( D3DRENDERSTATE_LIGHTING, FALSE );		
		pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
		pd3dDevice->SetMaterial( &mtrl );
	}	

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

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

	if( text1 )
		RenderEfxFace( 240, 140, 399 + tx1size, 200 + tx1size, text1_alpha, GetTexture( "data\\texts\\napis_9.jpg" ), pd3dDevice );

	if( text2 )
		RenderEfxFace( 500 - tx2posx, 266, 207, 96, text2_alpha, GetTexture( "data\\texts\\napis_3.jpg" ), pd3dDevice );

	pd3dDevice->SetTexture( 0, NULL );	
	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_WRAP0, D3DWRAPCOORD_0 | D3DWRAPCOORD_1 ); 
	pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND,  D3DBLEND_SRCALPHA );			
	pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_INVSRCALPHA );		

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

	if( Draw2ndTunnel )
	{
		pd3dDevice->SetRenderState( D3DRENDERSTATE_WRAP0, 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->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2 );

		mat = (D3DMATRIX)IdentMtx();
		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, TRUE );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_SRCBLEND,  D3DBLEND_INVSRCALPHA );			
		pd3dDevice->SetRenderState( D3DRENDERSTATE_DESTBLEND, D3DBLEND_SRCALPHA );			

		pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_ADD );
		pd3dDevice->SetTexture( 0, GetTexture( "data\\textures\\fg_Tentacle.jpg" ) );	
		pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, D3DFVF_TLVERTEX, Overground, 4, 0 );
		
		pd3dDevice->SetTextureStageState( 0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1 );
		pd3dDevice->SetRenderState( D3DRENDERSTATE_WRAP0, D3DWRAPCOORD_0 | D3DWRAPCOORD_1 ); 	
	}	

	if( renderMask )
	{
		pd3dDevice->SetRenderState( D3DRENDERSTATE_WRAP0, FALSE ); 	
		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 );
	}

	pd3dDevice->SetRenderState( D3DRENDERSTATE_ZENABLE, D3DZB_USEW );	
	pd3dDevice->SetRenderState( D3DRENDERSTATE_WRAP0, D3DWRAPCOORD_0 | D3DWRAPCOORD_1 ); 	

	pd3dDevice->SetTexture( 0, NULL );
	
	pd3dDevice->EndScene();
	
	return S_OK;
}

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

VOID fxDelete_Tunnel( LPDIRECT3DDEVICE7 pd3dDevice )
{	
	DeleteVolume( &volume );			

	DeleteObject3D( &sphere );
	DeleteObject3D( &morphed );
	DeleteObject3D( &morph1 );
	DeleteObject3D( &morph2 );

	SAFE_RELEASE( mask );

	LONG		i;

	for(  i = 0 ; i<5 ; i++ )
		DeleteObject3D( &torus[i] );

	DeleteObject3D( &blob[0] );
	DeleteObject3D( &blob[1] );

	if( pLineBlobInd )
		delete pLineBlobInd;
}
