www.pudn.com > sxdl.zip > tunnel.cpp


#include "tunnel.h" 
 
CTunnel::CTunnel ( int _Rings , int _Segments , int Tex1 , int Tex2 , int Tex3 , Color _color , int _ShaderId ) :  
	CCustomRenderer (  
		CVertex::PosNormalColorTex0 ,  
		( _Rings + 1 ) * ( _Segments + 1 ) ,  // VB Size  
		0 , // Usage normal  
		false , // static VB  
		2 * _Rings * ( _Segments + 1 ) , // IB Size  
		Tex1 , Tex2 , Tex3 , 0 ,  
		_ShaderId , 0 )  
{ 
	this->Rings    = _Rings ;   
	this->Segments = _Segments ;  
	this->color    = _color ;  
	// set vertex count and index count  
	Vertices = ( _Rings + 1 ) * ( _Segments + 1 ) ; 
	Indices  = 2 * _Rings * ( _Segments + 1 ) ; 
 
	Layer = SxDL::Models ;  
	Positions = new Vector4 [ _Rings ] ;  
} 
 
CTunnel::~CTunnel(void) 
{ 
	delete [ ] Positions ;  
} 
 
 
HRESULT CTunnel::OnPopulateBuffers ( void * pVertices , void * pIndices )						 
{  
	// The geometry of the tunnel is kind of cone based on the sphere code.  
	// 
	// Cast to our vertex format  
    VertexPosNormalColorTex0 * Vertex = ( VertexPosNormalColorTex0 * ) pVertices ;  
    unsigned short * Index = ( unsigned short * ) pIndices ;  
    // Establish constants used in sphere generation 
    float DeltaRingAngle  = ( D3DX_PI / Rings ); 
    float DeltaRingRadius = ( 1.0f / Rings ); 
    float DeltaSegAngle  = ( 2.0f * D3DX_PI / Segments ); 
	// Initialize vertex index  
	unsigned short VerticeIndex = 0 ;  
    // Generate the group of rings for the sphere 
    for( int ring = 0; ring < Rings + 1 ; ++ ring ) 
    { 
        float r0 = 1.0f - ring * DeltaRingRadius ; // critical change here  
        float y0 = cosf ( ring * DeltaRingAngle ) ; 
        // Generate the group of segments for the current ring 
        for( int seg = 0; seg < Segments + 1 ; ++ seg ) 
        { 
            float x0 =  r0 * sinf ( seg * DeltaSegAngle ) ; 
            float z0 =  r0 * cosf ( seg * DeltaSegAngle ) ; 
			// Add one vertices to the strip  
			Vertex->p     = D3DXVECTOR3 ( x0,z0,y0 ) ; // y and z swapped here   
			Vertex->n     = Vertex->p ;   
			// push the ring index as the red color  
			// for future use in the vertex shader  
			color = color & 0xFF00FFFF ;  
			Vertex->color = ( ring << 16 ) | color ; //  
			Vertex->tu    = - ( float ) seg  / ( float ) Segments; 
			Vertex->tv  
				 
				=   ( float ) ring / ( float ) Rings; 
			// Next vertex  
			++ Vertex ; 
			// add two indices except for last ring  
			if ( ring != Rings )  
			{ 
				* Index = VerticeIndex ;  
				++ Index  ; 
				* Index = VerticeIndex + ( ( unsigned short ) Segments + 1 ) ;  
				++ Index ; 
				++ VerticeIndex ;  
			} ;  
        } ; // end for seg  
    } // end for ring  
	return S_OK ;  
}  
 
HRESULT CTunnel::OnSetVertexShaderConstants ( LPDIRECT3DDEVICE9 Device , CEntity * Entity )	 
{ 
	// compute the position offsets 
	const float dt = 0.005f ;  
	float AbsoluteTime = Game->Timing.GetAbsolute ( ) ;  
	float Time = AbsoluteTime / 4.0f ;  
	float OmegaX = 2.0f + 0.15f * cosf ( 2.0f * Time ) ;  
	float OmegaY = 5.0f + 0.20f * cosf ( 1.5f * Time ) ;  
	for ( int i = 0 ; i < 20 ; ++ i )  
	{ 
		Positions [ i ].x = ( 0.0f + i * i * 0.01f ) * sinf ( OmegaX * ( Time + i * dt ) ) ;  
		Positions [ i ].y = ( 0.0f + i * i * 0.01f ) * sinf ( OmegaY * ( Time + i * dt ) + 5.0f ) ;  
		Positions [ i ].z = 0.0f ;  
		Positions [ i ].w = 0.0f ;  
		Device->SetVertexShaderConstantF ( 20 + i , (float*) & Positions [ i ] , 1 ) ; 
	} ;  
	// Set the shader matrix 
	D3DXMATRIX View       = Game->Camera.GetViewMatrix ( ) ; 
	D3DXMATRIX Projection = Game->Camera.GetProjectionMatrix ( ) ; 
	D3DXMATRIX ShaderMatrix ;  
	D3DXMatrixTranspose ( & ShaderMatrix, & ( Entity->GetWorldMatrix ( ) * View * Projection ) ); 
	Device->SetVertexShaderConstantF ( 4, ( const float * ) & ShaderMatrix , 4 ); 
	// Lighting vector and other constants 
	float Light[]    = { 1.00f, 0.00f, 0.00f, 0.00f }; 
	D3DCOLORVALUE CvDiffuse = CTools::ColorValueFromRGB ( color , 2.0f ) ;  
	float Diffuse []  = { CvDiffuse.r , CvDiffuse.g , CvDiffuse.b , CvDiffuse.a }; 
	float Ambient[]  = { 0.50f, 0.50f, 0.50f, 0.50f }; 
	// Set the lighting vertex shader constants 
	Device->SetVertexShaderConstantF ( 10, (float*)   Light,    1 ) ; 
	Device->SetVertexShaderConstantF ( 11, (float*)   Diffuse,  1 ) ; 
	Device->SetVertexShaderConstantF ( 12, (float*)   Ambient,  1 ) ; 
 
	return S_OK ;  
}  
 
HRESULT CTunnel::OnRender ( LPDIRECT3DDEVICE9 Device , CEntity * Entity ) 
{  
	// basic constants 
	float AbsoluteTime = Game->Timing.GetAbsolute ( ) ;  
	float SpeedUp = 0.5f * sinf ( AbsoluteTime ) ;  
	IsSpeedingUp = SpeedUp > 0.0f ;  
	float Time = 1.2f * AbsoluteTime + SpeedUp ;  
	D3DXVECTOR4 Zero ( 0.0f, 0.0f, 1.0f, 255.0f  ) ; 
	Device->SetVertexShaderConstantF (  0, (float*) & Zero,     1 ) ; 
	D3DXVECTOR4 One  ( 1.0f, 0.5f, 0.0f , Time / 2.0f ) ; 
	Device->SetVertexShaderConstantF (  1, (float*) & One,      1 ) ; 
	//  
	HRESULT hr ;  
	hr = Device->DrawIndexedPrimitive (  
		D3DPT_TRIANGLESTRIP, 0, 0, // min index  
		Vertices ,  0, // start index  
		Indices - 2 ) ; // number of primitives 
	Device->SetTexture ( 0 , Texture2 ) ;  
	// enable blending  
	Device->SetRenderState ( D3DRS_ALPHABLENDENABLE, TRUE ); 
	Device->SetRenderState ( D3DRS_SRCBLEND,  D3DBLEND_ONE ); 
	Device->SetRenderState ( D3DRS_DESTBLEND, D3DBLEND_ONE ); 
    Device->SetRenderState( D3DRS_ALPHATESTENABLE, TRUE ); 
	// Change sliding params  
	One = Vector4 ( 1.0f, 0.5f, Time / 1.3f , Time / 3.0f ) ; 
	Device->SetVertexShaderConstantF (  1, (float*) & One,      1 ) ; 
	hr = Device->DrawIndexedPrimitive (  
		D3DPT_TRIANGLESTRIP, 0, 0, // min index  
		Vertices ,  0, // start index  
		Indices - 2 ) ; // number of primitives 
	// disable alpha blending  
	Device->SetRenderState ( D3DRS_ALPHABLENDENABLE, FALSE ); 
    Device->SetRenderState( D3DRS_ALPHATESTENABLE, FALSE ); 
	return hr ;  
}