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 AIObjectiveMarker::RenderAlphas( double _predictionTime )
{
    bool objectiveActive = m_objectiveId == -1 || ((AIObjective *)g_app->m_location->GetBuilding( m_objectiveId ))->m_active;
    bool render = (!g_app->m_editing && g_prefsManager->GetInt( "RenderAIInfo", 0 ) != 0 && objectiveActive );
    if( g_app->m_editing || render)
    {
#ifdef LOCATION_EDITOR
        Building::RenderAlphas( _predictionTime );
        RGBAColour col;
        if( g_app->m_editing )
        {
            col.Set( 255, 0, 0 );
        }
        else if( m_id.GetTeamId() == 255 )
        {
            col.Set( 150, 150, 150 );
        }
        else
        {
            if( m_objectiveBuildingId != -1 &&
                fabs(sin(g_gameTime)) < 0.5)
            {
                col = RGBAColour(255, 255, 255, 255);
            }
            else
            {
                col = g_app->m_location->m_teams[ m_id.GetTeamId() ]->m_colour;
            }
        }
        RenderSphere( m_pos, 25.0, col );

        Building *b = g_app->m_location->GetBuilding( m_objectiveBuildingId );
        if( b )
        {
            RenderArrow( m_pos, b->m_pos, 5.0, col );
        }

        if( g_app->m_editing &&
            g_app->m_locationEditor->m_mode == LocationEditor::ModeBuilding &&
            g_app->m_locationEditor->m_selectionId == m_id.GetUniqueId() )
        {
            RenderSphere( m_pos, 30.0, RGBAColour( 255, 0, 0 ) );

            Vector3 triggerPos = m_pos;
            int numSteps = 20;
            glBegin( GL_LINE_LOOP );
            glLineWidth( 1.0 );
            glColor4f( 1.0f, 0.0f, 0.0f, 1.0f );
            for( int i = 0; i < numSteps; ++i )
            {
                float angle = 2.0f * M_PI * (float)i / (float) numSteps;
                Vector3 thisPos = triggerPos + Vector3( sinf(angle)*m_scanRange, 0.0f,
                                                        cosf(angle)*m_scanRange );
                thisPos.y = g_app->m_location->m_landscape.m_heightMap->GetValue( thisPos.x, thisPos.z );
                thisPos.y += 10.0f;
                glVertex3dv( thisPos.GetData() );
            }
            glEnd();
        }
#endif
    }
}
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 );
    }
}