void Render( int realX, int realY, bool highlighted, bool clicked)
    {
        Building *b = g_app->m_location->GetBuilding(g_app->m_locationEditor->m_selectionId);
        if( b )
        {
            if( b->m_id.GetTeamId() == m_teamId )
            {
                DarwiniaButton::Render( realX, realY, true, clicked );
            }
            else
            {
                DarwiniaButton::Render( realX, realY, highlighted, clicked );
            }
        }

        if( m_teamId == 255 )
        {
            glColor3ub( 100, 100, 100 );
        }
        else
        {
            RGBAColour col = g_app->m_location->m_teams[ m_teamId ].m_colour;
            glColor3ubv( col.GetData() );
        }

        glBegin( GL_QUADS );
            glVertex2i( realX + 30, realY + 4 );
            glVertex2i( realX + 40, realY + 4 );
            glVertex2i( realX + 40, realY + 12 );
            glVertex2i( realX + 30, realY + 12 );
        glEnd();
    }
void SafeArea::Render( double predictionTime )
{
    if( g_app->m_editing )
    {
        RGBAColour colour;

        if( m_id.GetTeamId() != 255 )
        {
            colour = g_app->m_location->m_teams[ m_id.GetTeamId() ]->m_colour;    
        }
        colour.a = 255;

#ifdef DEBUG_RENDER_ENABLED
        RenderSphere( m_pos, 20.0, colour );
#endif
        int numSteps = 30;
        double angle = 0.0;

        glColor4ubv(colour.GetData() );
        glLineWidth( 2.0 );
        glBegin( GL_LINE_LOOP );
        for( int i = 0; i <= numSteps; ++i )
        {
            double xDiff = m_size * iv_sin(angle);
            double zDiff = m_size * iv_cos(angle);
            Vector3 pos = m_pos + Vector3(xDiff,5,zDiff);
	        pos.y = g_app->m_location->m_landscape.m_heightMap->GetValue(pos.x, pos.z) + 10.0;
            if( pos.y < 2 ) pos.y = 2;
            glVertex3dv( pos.GetData() );
            angle += 2.0 * M_PI / (double) numSteps;
        }
        glEnd();
    }
    else
    {
/*
        double angle = g_gameTime * 2.0;
        Vector3 dif( m_size * iv_sin(angle), 0.0, m_size * iv_cos(angle) );
        
        Vector3 pos = m_pos + dif;
        pos.y = g_app->m_location->m_landscape.m_heightMap->GetValue( pos.x, pos.z ) + 5.0;
        g_app->m_particleSystem->CreateParticle( pos, g_upVector*2 + dif/30, Particle::TypeMuzzleFlash, 100.0 );

        pos = m_pos - dif;
        pos.y = g_app->m_location->m_landscape.m_heightMap->GetValue( pos.x, pos.z ) + 5.0;
        g_app->m_particleSystem->CreateParticle( pos, g_upVector*2 - dif/30, Particle::TypeMuzzleFlash, 100.0 );
*/
    }
    

    //char *entityTypeRequired = Entity::GetTypeName( m_entityTypeRequired );
    //g_editorFont.DrawText3DCentre( m_pos + Vector3(0,m_size/2,0), 10.0, "%d / %d %ss", m_entitiesCounted, m_entitiesRequired, entityTypeRequired );
}
void Nuke::RenderSub( double _predictionTime )
{
    if( m_subPos.y <= -35.0f ) return;

    glEnable        ( GL_TEXTURE_2D );
	glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
    glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR );
 	glEnable		( GL_BLEND );
    glDepthMask     ( false );    
    glDisable       ( GL_CULL_FACE );

    float size = 100.0f;
    Vector3 pos = m_subPos + m_subVel * _predictionTime;      

    Vector3 up = g_app->m_camera->GetUp();
    Vector3 right = g_app->m_camera->GetRight();

    char filename[256];
    char shadow[256];

    sprintf( filename, "sprites/sub.bmp" );
    sprintf(shadow, "sprites/subshadow.bmp");

    float alpha = max(m_subPos.y,0.0) / 30.0f;

    glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_COLOR );
    glBindTexture   (GL_TEXTURE_2D, g_app->m_resource->GetTexture(shadow));
    glColor4f   ( 1.0f, 1.0f, 1.0f, 0.0f );
    glBegin( GL_QUADS );
        glTexCoord2i( 0, 0 );       glVertex3dv( (pos - right * size - up * size).GetData() );
        glTexCoord2i( 0, 1 );       glVertex3dv( (pos - right * size + up * size).GetData() );
        glTexCoord2i( 1, 1 );       glVertex3dv( (pos + right * size + up * size).GetData() );
        glTexCoord2i( 1, 0 );       glVertex3dv( (pos + right * size - up * size).GetData() );    
    glEnd();

    RGBAColour col = g_app->m_location->m_teams[m_id.GetTeamId()]->m_colour;
    col.a = alpha * 255;
    glBlendFunc     ( GL_SRC_ALPHA, GL_ONE );
    glBindTexture   ( GL_TEXTURE_2D, g_app->m_resource->GetTexture( filename ) );
    glColor4ubv( col.GetData() );  
    glBegin( GL_QUADS );
        glTexCoord2i( 0, 0 );       glVertex3dv( (pos - right * size - up * size).GetData() );
        glTexCoord2i( 0, 1 );       glVertex3dv( (pos - right * size + up * size).GetData() );
        glTexCoord2i( 1, 1 );       glVertex3dv( (pos + right * size + up * size).GetData() );
        glTexCoord2i( 1, 0 );       glVertex3dv( (pos + right * size - up * size).GetData() );    
    glEnd();
    
    glEnable        ( GL_CULL_FACE );
	glDisable       ( GL_BLEND );
    glDisable       ( GL_TEXTURE_2D );
    glDepthMask     ( true );
    glBlendFunc     ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA );
}
void LocationEditor::RenderUnit(InstantUnit *_iu)
{
	char *typeName = Entity::GetTypeName(_iu->m_type);
	
	float landHeight = g_app->m_location->m_landscape.m_heightMap->GetValue(_iu->m_posX, _iu->m_posZ);
	glColor4f( 1.0, 1.0, 1.0, 1.0 );
    g_editorFont.DrawText3DCentre(Vector3(_iu->m_posX, landHeight + 15.0, _iu->m_posZ),
								  15.0, "%d %s(s)", _iu->m_number, typeName);


	// Render troops
	int maxX = (int)iv_sqrt(_iu->m_number);
	int maxZ = _iu->m_number / maxX;
	float pitch = 10.0;
	float offsetX = -maxX * pitch * 0.5;
	float offsetZ = -maxZ * pitch * 0.5;
	RGBAColour colour;
    if( _iu->m_teamId >= 0 ) colour = g_app->m_location->m_teams[_iu->m_teamId]->m_colour;
	colour.a = 200;
    glColor4ubv(colour.GetData());
    
    Vector3 camUp = g_app->m_camera->GetUp() * 5.0;
    Vector3 camRight = g_app->m_camera->GetRight() * 5.0;

    glDisable   (GL_CULL_FACE );
    glEnable    (GL_BLEND);
    glBlendFunc (GL_SRC_ALPHA, GL_ONE);
    glDepthMask (false);
	glBegin     (GL_QUADS);
    
    //
    // Render dots for the number and team of the unit

	for (int x = 0; x < maxX; ++x)
	{
		for (int z = 0; z < maxZ; ++z)
		{
			Vector3 pos(_iu->m_posX + offsetX + x * pitch, 0,
						_iu->m_posZ + offsetZ + z * pitch);
			pos.y = g_app->m_location->m_landscape.m_heightMap->GetValue(pos.x, pos.z) + 2.0;
			glVertex3dv( (pos - camUp - camRight).GetData() );
            glVertex3dv( (pos - camUp + camRight).GetData() );
            glVertex3dv( (pos + camUp + camRight).GetData() );
            glVertex3dv( (pos + camUp - camRight).GetData() );
		}
	}

    glEnd();


    //
    // Render our spread circle

    if( m_mode == ModeInstantUnit )
    {
        int numSteps = 30;
        float angle = 0.0;

        colour.a = 100;
        glColor4ubv(colour.GetData() );
        glLineWidth( 2.0 );
        glBegin( GL_LINE_LOOP );
        for( int i = 0; i <= numSteps; ++i )
        {
            float xDiff = _iu->m_spread * iv_sin(angle);
            float zDiff = _iu->m_spread * iv_cos(angle);
            Vector3 pos = Vector3(_iu->m_posX, 0.0, _iu->m_posZ) + Vector3(xDiff,5,zDiff);
	        pos.y = g_app->m_location->m_landscape.m_heightMap->GetValue(pos.x, pos.z) + 10.0;
            if( pos.y < 2 ) pos.y = 2;
            glVertex3dv( pos.GetData() );
            angle += 2.0 * M_PI / (float) numSteps;
        }
        glEnd();
    }
    

    glDisable   (GL_BLEND);
    glDepthMask (true);
    glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable    (GL_CULL_FACE );

}
void Nuke::RenderHistory( double _predictionTime )
{
    if( m_history.Size() > 0 && m_id.GetTeamId() != 255 )
    {
        glBindTexture( GL_TEXTURE_2D, g_app->m_resource->GetTexture( "textures/laser.bmp" ) );

        Vector3 predictedPos = m_pos + m_vel * SERVER_ADVANCE_PERIOD;
        Vector3 lastPos = predictedPos;

        RGBAColour colour = g_app->m_location->m_teams[m_id.GetTeamId()]->m_colour;
        if( m_id.GetTeamId() == g_app->m_location->GetMonsterTeamId() )
        {
            glBlendFunc     ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_COLOR );
            colour.Set( 255, 255, 255, 0 );
        }

        for( int i = 0; i < m_history.Size(); ++i )
        {
            Vector3 historyPos, thisPos;
			thisPos = historyPos = *m_history[i];

            Vector3 diff = thisPos - lastPos;
            lastPos += diff * 0.1f;
            if( m_id.GetTeamId() != g_app->m_location->GetMonsterTeamId() )
            {
                colour.a = 255 - 255 * (float) i / (float) m_history.Size();
            }

            glColor4ubv( colour.GetData() );

            Vector3 lengthVector = (thisPos - lastPos).Normalise();
	        lengthVector.SetLength((thisPos - lastPos).Mag());
            Vector3 fromPos = lastPos;
            Vector3 toPos = thisPos;//lastPos - lengthVector;

            Vector3 midPoint        = fromPos + (toPos - fromPos)/2.0f;
            Vector3 camToMidPoint   = g_app->m_camera->GetPos() - midPoint;
            float   camDistSqd      = camToMidPoint.MagSquared();
            Vector3 rightAngle      = (camToMidPoint ^ ( midPoint - toPos )).Normalise();
            
            //rightAngle *= 0.8f;
            rightAngle.SetLength(5.0f);

            glBegin( GL_QUADS );
                glTexCoord2i(0,0);      glVertex3dv( (fromPos - rightAngle).GetData() );
                glTexCoord2i(0,1);      glVertex3dv( (fromPos + rightAngle).GetData() );
                glTexCoord2i(1,1);      glVertex3dv( (toPos + rightAngle).GetData() );                
                glTexCoord2i(1,0);      glVertex3dv( (toPos - rightAngle).GetData() );                     

                glTexCoord2i(0,0);      glVertex3dv( (fromPos - rightAngle).GetData() );
                glTexCoord2i(0,1);      glVertex3dv( (fromPos + rightAngle).GetData() );
                glTexCoord2i(1,1);      glVertex3dv( (toPos + rightAngle).GetData() );                
                glTexCoord2i(1,0);      glVertex3dv( (toPos - rightAngle).GetData() );                     

                glTexCoord2i(0,0);      glVertex3dv( (fromPos - rightAngle).GetData() );
                glTexCoord2i(0,1);      glVertex3dv( (fromPos + rightAngle).GetData() );
                glTexCoord2i(1,1);      glVertex3dv( (toPos + rightAngle).GetData() );                
                glTexCoord2i(1,0);      glVertex3dv( (toPos - rightAngle).GetData() );                     
            glEnd();

            lastPos = historyPos;
        }
    }
}
void Nuke::Render( double _predictionTime )
{
    if( m_renderMarker )
    {
        RenderGroundMarker();
    }
    RenderSub( _predictionTime );
    if( m_exploded )
    {
        //RenderDeaths();
    }
    else
    {
        if( !m_launched ) return;

        Vector3 front = m_front;
        front.RotateAroundY( M_PI / 2.0f );
        Vector3 predictedPos = m_pos + m_vel * _predictionTime;;
        Vector3 entityUp = m_front;
        Vector3 entityRight (front ^ entityUp);

        Vector3 lengthVector = m_vel;
        lengthVector.SetLength( 10.0f );
        Vector3 fromPos = predictedPos;
        Vector3 toPos = predictedPos - lengthVector;

        Vector3 midPoint        = fromPos + (toPos - fromPos)/2.0f;
        Vector3 camToMidPoint   = g_app->m_camera->GetPos() - midPoint;
        float   camDistSqd      = camToMidPoint.MagSquared();
        Vector3 rightAngle      = (camToMidPoint ^ ( midPoint - toPos )).Normalise();

        entityRight = rightAngle;

        float size = 10.0f;  
        size *= (1.0f + 0.03f * (( m_id.GetIndex() * m_id.GetUniqueId() ) % 10));
        entityRight *= size;
        entityUp *= size * 2.0f;

        glDepthMask     ( false );
        glEnable        ( GL_BLEND );
        glBlendFunc     ( GL_SRC_ALPHA, GL_ONE );
        glEnable        ( GL_TEXTURE_2D );
        glBindTexture( GL_TEXTURE_2D, g_app->m_resource->GetTexture( "sprites/nuke.bmp" ) );

        RGBAColour colour = g_app->m_location->m_teams[m_id.GetTeamId()]->m_colour;
        if( m_id.GetTeamId() == g_app->m_location->GetMonsterTeamId() )
        {
            glBlendFunc     ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_COLOR );
            colour.Set( 255, 255, 255, 0 );
        }
        glColor4ubv(colour.GetData());

        glBegin(GL_QUADS);
            glTexCoord2i(0, 1);     glVertex3dv( (predictedPos - entityRight + entityUp).GetData() );
            glTexCoord2i(1, 1);     glVertex3dv( (predictedPos + entityRight + entityUp).GetData() );
            glTexCoord2i(1, 0);     glVertex3dv( (predictedPos + entityRight).GetData() );
            glTexCoord2i(0, 0);     glVertex3dv( (predictedPos - entityRight).GetData() );
        glEnd();

        RenderHistory( _predictionTime );

        glShadeModel    ( GL_FLAT );
        glDisable       ( GL_TEXTURE_2D );
        glDepthMask     ( true );
    }
}