#include <gl\glut.h>
#include "Bubbles.h"


/*
	Yay, bubbles!  
	This bubble system works similar to the particle system, but bubbles travel upward
	and are transparent spheres.  Would be nice to use some refractive bubbles to improve
	realism and what not, or just use a basic spheremap to simulate reflections.
*/

extern float myRandom();
extern float queryElapsedTime();


//-----------------------------------------------------------------------------
// Name: CBubbleManager::CBubbleManager
// Desc: Class constructor; initializes bubble system.
//-----------------------------------------------------------------------------
CBubbleManager::CBubbleManager( int BubbleCount, float fRange, float fMaxHeight,
								float fMaxRadius, float fMinRadius )
{
	// Set bubble count (default 50)
	m_BubbleCount = BubbleCount;

	// Set bubble range (default 500)
	m_fRange = fRange;

	// Set max height bubble can reach (default 300)
	m_fMaxHeight = fMaxHeight;

	// Allocate bubble array
	m_pBubbleAttr = new BubbleAttributes[BubbleCount];

	// Give each bubble a random position and radius
	for( int i = 0; i < BubbleCount; i++ )
	{
		float x = fRange * myRandom();
		float z = fRange * myRandom();
		float y = fMaxHeight * myRandom();

		if( (i%3) == 1 )
			x = -x;
		if( (i%2) == 0 )
			z = -z;

		m_pBubbleAttr[i].fRadius = ( ( fMaxRadius - 1.0f ) * myRandom() ) + fMinRadius;
		m_pBubbleAttr[i].fRiseVelocity = 15.0f;
		m_pBubbleAttr[i].fAlpha = 0.5f;
		m_pBubbleAttr[i].vecPosition.set( x, y, z );
	}
}

//-----------------------------------------------------------------------------
// Name: CBubbleManager::~CBubbleManager
// Desc: Class deconstructor; Uninitializes bubble system
//-----------------------------------------------------------------------------
CBubbleManager::~CBubbleManager()
{
	if( m_pBubbleAttr )
	{
		delete [] m_pBubbleAttr;
		m_pBubbleAttr = 0;
	}
}

//-----------------------------------------------------------------------------
// Name: CBubbleManager::Render
// Desc: Renders the bubbles
//-----------------------------------------------------------------------------
void CBubbleManager::Render()
{
	// Render each bubble with alpha blending enabled
	glPushAttrib( GL_ALL_ATTRIB_BITS );
	glEnable( GL_BLEND );
	glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
//	glCullFace( GL_CCW );

	// Enable sphere mapping
	glEnable( GL_TEXTURE_2D );
	glTexGeni( GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
	glTexGeni( GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP );
	glEnable( GL_TEXTURE_GEN_S );
	glEnable( GL_TEXTURE_GEN_T );

	glBindTexture( GL_TEXTURE_2D, m_uTexture );

	for( int i = 0; i < m_BubbleCount; i++ )
	{
		glPushMatrix();
		glTranslatef( m_pBubbleAttr[i].vecPosition.get()[0],
					  m_pBubbleAttr[i].vecPosition.get()[1],
					  m_pBubbleAttr[i].vecPosition.get()[2] );
		glColor4f( 1.0f, 1.0f, 1.0f, m_pBubbleAttr[i].fAlpha );
		glutSolidSphere( m_pBubbleAttr[i].fRadius, 20, 20 );
		glPopMatrix();
	}

	glPopAttrib();
}

//-----------------------------------------------------------------------------
// Name: CBubbleManager::Update
// Desc: Updates each bubble in the bubble manager. When a bubble reaches it's
//		 peak height, let it fade out before we send it back to the bottom.
//-----------------------------------------------------------------------------
void CBubbleManager::Update()
{
	float fTime = 0.0f, fDeltaTime;
	static float fLastTime = 0.0f;

	// Update timing variables
	fTime = queryElapsedTime();
	fDeltaTime = fTime - fLastTime;
	fLastTime = fTime;

	// Update each bubble by adding the particle velocity multiplied
	// with fDeltaTime.  If the bubble reaches the maximum height, send it 
	// to the bottom and give it a new position.
	for( int i = 0; i < m_BubbleCount; i++ )
	{
		m_pBubbleAttr[i].vecPosition.get()[1] += m_pBubbleAttr[i].fRiseVelocity * fDeltaTime;

		if( m_pBubbleAttr[i].vecPosition.get()[1] > m_fMaxHeight )
		{
			// Let the bubble fade out before we reset it.
			if( m_pBubbleAttr[i].fAlpha > 0.0f )
			{
				m_pBubbleAttr[i].fAlpha -= 0.01f;
			}
			else
			{
				float x = m_fRange * myRandom();
				float z = m_fRange * myRandom();

				if( (i%3) == 1 )
					x = -x;
				if( (i%2) == 0 )
					z = -z;

				m_pBubbleAttr[i].vecPosition.set( x, -80.0f, z );
				m_pBubbleAttr[i].fAlpha = 0.3f;
			}
		}
	}
}
