#include "Line.h"
#include "PlanView.h"

#define MODULE_NAME "AVM_Line"
#define AVM_DEBUG_SWITCH    0
#include "Avm_log.h"


static const char *vshader_line = {
    "precision highp float;"
    "attribute  vec2     line_position;"
    "attribute  vec4    line_color;"

    "varying    vec4    line_outColor;"

    "void main()"
    "{"
    "    vec4    pos     =   vec4(line_position.x, line_position.y, 0.0, 1.0);"
    "   gl_Position     =   pos;"
    "    gl_PointSize     =   3.0;"
    "   line_outColor   =   line_color;"
    "}"
};

static const char *fshader_line = {
    "precision highp float;"
    "varying  vec4   line_outColor;"

    "void main()"
    "{"
    "   gl_FragColor    =   line_outColor;"
    "}"
};

#define ATTR_POSITION_Line    "line_position"
#define ATTR_COLOR_Line          "line_color"

static UndistViewTrack g_UndistTrack;
static UndistLRViewTrack g_UndistLRTrack;

static GLuint programLine = 0;
static GLuint vsLine_position2 = 100;
static GLuint vsLine_color4 = 100;
static float lineHeight = 0.1780;
static VehicleTracks stVehicleTracks;
static BirdviewTrack stBirdviewTrack;
static Corners *g_pCorners = NULL;
static Corners  g_stDefaultCorners = {0};       /*默认加点坐标，当读取luts_Corner失败时使用*/
static ModFrameInfo g_stModFrameInfo[4];

void esInitProgram_Line()
{
    GLuint hdVerShader = 0;
    GLuint hdFrgShader = 0;
    GLuint hdLineAttrib[2] = {0,0};

    esApplyAttribHandle(2, hdLineAttrib);
    vsLine_position2 = hdLineAttrib[0];
    vsLine_color4 = hdLineAttrib[1];

    esLoadShader(&vshader_line, &fshader_line, &hdVerShader, &hdFrgShader);
    programLine = glCreateProgram();
    glAttachShader(programLine , hdVerShader);
    glAttachShader(programLine , hdFrgShader);
    glBindAttribLocation(programLine , vsLine_position2, ATTR_POSITION_Line);
    glBindAttribLocation(programLine , vsLine_color4, ATTR_COLOR_Line);
    glLinkProgram(programLine);
}


typedef struct
{
    // Handle to a program object
    GLuint programObj;

    // Attribute locations
    GLint   positionLoc3f;
    GLint   colorLoc4f;

    // Uniform locations
    GLint   projectionLoc;
    GLint   camMatrixLoc;
} OesObj_3DTracks;

OesObj_3DTracks obj3DTracks;

void esInitProgram_3DLine()
{
    static const char vshader_3DTracks[] =
        "precision  mediump float;"

        "attribute vec3 tracks_position;"
        "attribute vec4 tracks_color;"

        "uniform   mat4 tracks_projection;"
        "uniform   mat4 tracks_matView;"

        "varying mediump vec4 tracks_outColor;"

        "void main()"
        "{"
        "    vec4    pos       =   vec4(tracks_position.xyz, 1.0);"
        "    gl_Position       =   tracks_projection * (tracks_matView * pos);"
        "    gl_PointSize      =   3.0;"
        "    tracks_outColor      =   tracks_color;"
        "}";

    static const char fshader_3DTracks[] =
        "precision highp float;\n"
        "varying mediump vec4 tracks_outColor;"

        "void main(void)\n"
        "{\n"
        "    gl_FragColor    =   tracks_outColor;\n"
        "}";

    obj3DTracks.programObj = esLoadProgram(vshader_3DTracks, fshader_3DTracks);

    obj3DTracks.positionLoc3f = glGetAttribLocation(obj3DTracks.programObj, "tracks_position");
    obj3DTracks.colorLoc4f    = glGetAttribLocation(obj3DTracks.programObj, "tracks_color");

    obj3DTracks.projectionLoc = glGetUniformLocation(obj3DTracks.programObj,  "tracks_projection");
    obj3DTracks.camMatrixLoc  = glGetUniformLocation(obj3DTracks.programObj,  "tracks_matView");
}

void LineInit()
{
    esInitProgram_Line();
    esInitProgram_3DLine();

    GetStaticTracks((float*)&g_UndistTrack, (float*)&g_UndistLRTrack);
    AVM_DEBUG("LineInit: leave GetStaticTracks\n");
}

void SaleCornerInit(char *pathCornerLuts)
{
    int datasize = 0;

    if (NULL == g_pCorners)
    {
        g_pCorners = (Corners *)malloc(sizeof(Corners));
    }
    datasize = LoadFile(pathCornerLuts, pathCornerLuts, (UChar **)&g_pCorners, 1);
    if (datasize != sizeof(Corners))
    {
        AVM_ERROR("read %s failed\n", pathCornerLuts);
        memcpy(g_pCorners, &g_stDefaultCorners, sizeof(Corners));
        AVM_DEBUG("use Default corners\n");
    }
}

/*
*移动角点，更新角点坐标
*参数:
*whichCam: 移动哪个相机视图中的角点, 0~3对应左右前后
*direction: 移动方向, 1-4对应上下左右
*stepsize: 移动步长,单位:一个像素
*/
void SaleCornerMove(int whichCam, int direction, int stepSize)
{

}

void SaleCornerConfirm(char *pathCornerLuts)
{

    WriteDatatoFile(pathCornerLuts, g_pCorners, sizeof(Corners));
}


void CornerRender(float x, float y, int selected)
{

}

/*
*
*/
void SaleCornerRender(int whichCam)
{
    int screenCoord[2] = {1, 1};
    float openglCoord[2] = {1, 1};

    ScreenCoordConvert(1280, 720, screenCoord, openglCoord, 2);
    CornerRender(0.5, 0.5, 1);
}


enumTracks SetPlaneTracksType(avmViewState viewType)
{
    enumTracks whichTrack;

    switch(viewType)
    {
        case AVM_DISPLAY_STATE_CORRECT_FRONT:
            whichTrack = TRACKS_CORRECTFRONT;
            break;

        case AVM_DISPLAY_STATE_CORRECT_REAR:
            whichTrack = TRACKS_CORRECTREAR;
            break;

        case AVM_DISPLAY_STATE_CORRECT_LEFT:
            whichTrack = TRACKS_CORRECTLEFT;
            break;

        case AVM_DISPLAY_STATE_CORRECT_RIGHT:
            whichTrack = TRACKS_CORRECTRIGHT;
            break;

        case AVM_DISPLAY_STATE_CORRECT_LR_FRONT:
            whichTrack = TRACKS_CORRECT_LR_FRONT;
            break;

        case AVM_DISPLAY_STATE_CORRECT_LR_REAR:
            whichTrack = TRACKS_CORRECT_LR_REAR;
            break;

        case AVM_DISPLAY_STATE_3D_TOP:
            whichTrack = TRACKS_3DTOPVIEW;
            break;

        default:
            whichTrack = TRACKS_NONE;
            break;
    }

    return whichTrack;
}


static void convertofflinepointsCoord(double u, double v, float *x, float *y, int whichview)
{
    u /= 1280;
    v /= 720;
    /* 0 front 1 back 2 left 3 right for algorithm of offlinecali  */
    switch (whichview)
    {
        case 0:
            *x = -1.0 + u;
            *y = 1.0 - v;
            break;
        case 1:
            *x = u;
            *y = 1.0 - v;
            break;
        case 2:
            *x = -1.0 + u;
            *y = -v;
            break;
        case 3:
            *x = u;
            *y = -v;
            break;
    }
}


static void cornersrenderpoint(float x, float y, int selected)
{
    GLfloat Ver[8];
    GLfloat Cor[16];
    int k = 0;

    glUseProgram(programLine);
    glEnableVertexAttribArray(vsLine_position2);
    glEnableVertexAttribArray(vsLine_color4);
    glEnable(GL_BLEND);
//    glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
    glLineWidth(2.0);

    /*Fyh:N the point you are moving is red */
    if (1 == selected)
    {
        for (k = 0; k < 4; k++)
        {
            Cor[4*k] = 1.0;            // N: Red
            Cor[4*k+1] = 0.0;
            Cor[4*k+2] = 0.0;
            Cor[4*k+3] = 0.5;
        }
    }
    else
    {
        for (k = 0; k < 4; k++)
        {
            Cor[4*k] = 1.0;            // N: R+G= Yellow
            Cor[4*k+1] = 1.0;
            Cor[4*k+2] = 0.0;
            Cor[4*k+3] = 0.5;
        }
    }
    Ver[0] = x - 0.01; Ver[1] = y;
    Ver[2] = x + 0.01; Ver[3] = y;
    Ver[4] = x; Ver[5] = y + 0.02;
    Ver[6] = x; Ver[7] = y - 0.02;

    glVertexAttribPointer(vsLine_position2, 2, GL_FLOAT, GL_FALSE, 0, Ver);
    glVertexAttribPointer(vsLine_color4, 4, GL_FLOAT, GL_FALSE, 0, Cor);
    glDrawArrays(GL_LINES, 0, 4);

    glDisable(GL_BLEND);
    glDisableVertexAttribArray(vsLine_position2);
    glDisableVertexAttribArray(vsLine_color4);
    glUseProgram(0);
}


void lineOfflineCorner(Coord offlineCorner[4][23])
{
    float x, y;
    int i, j;

    do
    {
        for (i = 0; i < 4; i++)
        {
            for (j = 0; j < 23; j++)
            {
                if ((offlineCorner[i][j].x != -1.0) && (offlineCorner[i][j].y != -1.0))
                {
                    convertofflinepointsCoord(offlineCorner[i][j].x, offlineCorner[i][j].y,
                                                &x, &y, i);
                    cornersrenderpoint(x, y, 0);
                }
            }
        }
    } while(0);
}

/*绘制售后标定时的角点*/
void LineSaleCaliCorner ( int witchView )
{

}


void ConvertOriModCorrd ( float *outVer, ModFrame modInfo )
{
    int ScreenCoord[8] = {0};   /* leftdown.xy - leftup.xy - rightup.xy -rightdown.xy */
    float openglCoord[8] = {0.0};

    ScreenCoord[0] = modInfo.x;
    ScreenCoord[1] = modInfo.y;
    ScreenCoord[4] = modInfo.x + modInfo.weight;
    ScreenCoord[5] = modInfo.y + modInfo.hight;

    ScreenCoord[2] = ScreenCoord[0];
    ScreenCoord[3] = ScreenCoord[5];
    ScreenCoord[6] = ScreenCoord[4];
    ScreenCoord[7] = ScreenCoord[1];

    ScreenCoordConvert(1280, 720, ScreenCoord, openglCoord, 8);
    memcpy(outVer, openglCoord, sizeof(openglCoord));
}

void LineOrigViewMOD ( int camIdx )
{
    int i = 0;
    int modidx = 0;
    float modVer[8] = {0.0};
    float modCor[16] = {
        1.0f, 1.0f, 0.0f, 1.0f,
        1.0f, 1.0f, 0.0f, 1.0f,
        1.0f, 1.0f, 0.0f, 1.0f,
        1.0f, 1.0f, 0.0f, 1.0f
    };

    do
    {
        for (i=0; i<4; i++)
        {
            if ((camIdx == g_stModFrameInfo[i].carmeraIndex) && (0 < g_stModFrameInfo[i].framenum))
            {
                modidx = i;
                break;
            }
        }
        if (4 <= i)
        {
            break;
        }

        glUseProgram(programLine);
        glEnableVertexAttribArray(vsLine_position2);
        glEnableVertexAttribArray(vsLine_color4);
        glLineWidth(2.0);
        for (i = 0; i < g_stModFrameInfo[modidx].framenum; i++)
        {
            ConvertOriModCorrd(modVer, g_stModFrameInfo[modidx].frames[i]);
            glVertexAttribPointer(vsLine_position2, 2, GL_FLOAT, GL_FALSE, 0, modVer);
            glVertexAttribPointer(vsLine_color4, 4, GL_FLOAT, GL_FALSE, 0, modCor);
            glDrawArrays(GL_LINE_LOOP, 0, 4);
        }

        glDisableVertexAttribArray(vsLine_position2);
        glDisableVertexAttribArray(vsLine_color4);
        glUseProgram(0);
    } while(0);

}

void LineUndistViewMOD_Front ()
{

}
void LineUndistViewMOD_Rear ()
{

}
void LineUndistViewMOD_Left ()
{

}
void LineUndistViewMOD_Right ()
{

}

void LineTopViewModRender ()
{

}


static void Dynamic2DApaTracksrender(LineSegmentLarge staDynamic[][2], LineSegmentLarge *staDynamicS)
{

}


static void Dynamic2DNoApaTracksrender(LineSegmentLarge staDynamic[][2], LineSegmentLarge *staDynamicS)
{
    int k = 0,i = 0,t = 0;
    GLfloat Ver[800];
    GLfloat Cor[1600];
    GLfloat eveR, eveG, eveB, eveA;
    int changePoint = 60;

    glUseProgram(programLine);
    glEnableVertexAttribArray(vsLine_position2);
    glEnableVertexAttribArray(vsLine_color4);
    glEnable(GL_BLEND);
//    glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
//    glHint(GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES, GL_NICEST);
    glLineWidth(4.0);

    for (t = 0; t < 3; t++)
    {
        eveA = (0.0-1.0) / (167 - changePoint);
        /* draw right margin line and left margin line */
        for (k = 0; k < 167; k++)
        {
            Cor[4*k] = 251.0/255.0;
            Cor[4*k+1] = 180.0/255.0;
            Cor[4*k+2] = 80.0/255.0;
            if (k<changePoint)
            {
                Cor[4*k+3] = 1.0;
            }
            else
            {
                Cor[4*k+3] = 1.0+eveA*(k-changePoint);
            }
        }
        {
            k=0;
            i=0;
            do
            {
                Ver[2*k] = staDynamic[t][0].usaXCoor[k];
                Ver[2*k+1] = staDynamic[t][0].usaYCoor[k];
                k++;
            }while(k < 167);
            glVertexAttribPointer(vsLine_position2, 2, GL_FLOAT, GL_FALSE, 0, Ver);
            glVertexAttribPointer(vsLine_color4, 4, GL_FLOAT, GL_FALSE, 0, Cor);
            glDrawArrays(GL_LINE_STRIP, 0, k);
            glDrawArrays(GL_POINTS, 0, k);
        }
        {
            k=0;
            i=0;
            do
            {
                Ver[2*k] = staDynamic[t][1].usaXCoor[k];
                Ver[2*k+1] = staDynamic[t][1].usaYCoor[k];
                k++;
            }while(k < 167);
            glVertexAttribPointer(vsLine_position2, 2, GL_FLOAT, GL_FALSE, 0, Ver);
            glVertexAttribPointer(vsLine_color4, 4, GL_FLOAT, GL_FALSE, 0, Cor);
            glDrawArrays(GL_LINE_STRIP, 0, k);
            glDrawArrays(GL_POINTS, 0, k);
        }
    }

    /* draw horizontal line */
    for (k = 0; k < 200; k++)
    {
        Cor[4*k] = 1.0;
        Cor[4*k+1] = 40.0 / 255.0;
        Cor[4*k+2] = 22.0 / 255.0;
        Cor[4*k+3] = 1.0;
    }
    {
        k=0;
        do
        {
            Ver[2*k] = staDynamicS->usaXCoor[k];
            Ver[2*k+1] = staDynamicS->usaYCoor[k];
            k++;
        }while(k < 200);
        glVertexAttribPointer(vsLine_position2, 2, GL_FLOAT, GL_FALSE, 0, Ver);
        glVertexAttribPointer(vsLine_color4, 4, GL_FLOAT, GL_FALSE, 0, Cor);
        glDrawArrays(GL_LINE_STRIP, 0, k);
    }
//    glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
//    glDisable(GL_SAMPLE_COVERAGE);
    /* draw right wheel track filler */
    eveR = (251.0-240.0)/(167.0 - changePoint);
    eveG = (180.0-120.0)/(167.0 - changePoint);
    eveB = (80.0-0.0)/(167.0 - changePoint);
    eveA = (0.0-0.5)/(167.0 - changePoint);
    for (i = 0, k = 0; i < 167; i++)
    {
        if (k<changePoint)
        {
            Cor[8*i] = 240.0/255.0;
            Cor[8*i+1] = 120.0/255.0;
            Cor[8*i+2] = 0.0/255.0;
            Cor[8*i+3] = 0.5;
            Cor[8*i+4] = 240.0/255.0;;
            Cor[8*i+5] = 120.0/255.0;
            Cor[8*i+6] = 0.0/255.0;
            Cor[8*i+7] = 0.5;
        }
        else
        {
            Cor[8*i] = (240.0+eveR*(k-changePoint))/255.0;
            Cor[8*i+1] = (120.0+eveG*(k-changePoint))/255.0;
            Cor[8*i+2] = (0.0+eveB*(k-changePoint))/255.0;
            Cor[8*i+3] = (0.5+eveA*(k-changePoint));
            Cor[8*i+4] = (240.0+eveR*(k-changePoint))/255.0;
            Cor[8*i+5] = (120.0+eveG*(k-changePoint))/255.0;
            Cor[8*i+6] = (0.0+eveB*(k-changePoint))/255.0;
            Cor[8*i+7] = (0.5+eveA*(k-changePoint));
        }
        k++;
    }
    {
        glCullFace(GL_FRONT);
        k=0;
        do
        {
            Ver[4*k] = staDynamic[1][0].usaXCoor[k];
            Ver[4*k+1] = staDynamic[1][0].usaYCoor[k];
            Ver[4*k+2] = staDynamic[2][0].usaXCoor[k];
            Ver[4*k+3] = staDynamic[2][0].usaYCoor[k];
            k++;
        }while(k < 167);
        glVertexAttribPointer(vsLine_position2, 2, GL_FLOAT, GL_FALSE, 0, Ver);
        glVertexAttribPointer(vsLine_color4, 4, GL_FLOAT, GL_FALSE, 0, Cor);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 2*k);
        glCullFace(GL_BACK);
    }
    /* draw left wheel track filler */
    {
        k=0;
        do
        {
            Ver[4*k] = staDynamic[1][1].usaXCoor[k];
            Ver[4*k+1] = staDynamic[1][1].usaYCoor[k];
            Ver[4*k+2] = staDynamic[2][1].usaXCoor[k];
            Ver[4*k+3] = staDynamic[2][1].usaYCoor[k];
            k++;
        }while(k < 167);
        glVertexAttribPointer(vsLine_position2, 2, GL_FLOAT, GL_FALSE, 0, Ver);
        glVertexAttribPointer(vsLine_color4, 4, GL_FLOAT, GL_FALSE, 0, Cor);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 2*k);
    }
#ifdef WHITE_FILLTER
    /* draw filler between right wheel track and right boundary  */
    eveR = (130.0-68.0)/(167.0 - changePoint);
    eveG = (130.0-68.0)/(167.0 - changePoint);
    eveB = (130.0-68.0)/(167.0 - changePoint);
    eveA = (0.0-0.5)/(167.0 - changePoint);
    for (i = 0, k = 0; i < 167; i++)
    {
        if (k<changePoint)
        {
            Cor[8*i] = 68.0/255.0;
            Cor[8*i+1] = 68.0/255.0;
            Cor[8*i+2] = 68.0/255.0;
            Cor[8*i+3] = 0.5;
            Cor[8*i+4] = 68.0/255.0;
            Cor[8*i+5] = 68.0/255.0;
            Cor[8*i+6] = 68.0/255.0;
            Cor[8*i+7] = 0.5;
        }
        else
        {
            Cor[8*i]   = (68.0+eveR*(k-changePoint))/255.0;
            Cor[8*i+1] = (68.0+eveG*(k-changePoint))/255.0;
            Cor[8*i+2] = (68.0+eveB*(k-changePoint))/255.0;
            Cor[8*i+3] = (0.5+eveA*(k-changePoint));
            Cor[8*i+4] = (68.0+eveR*(k-changePoint))/255.0;
            Cor[8*i+5] = (68.0+eveG*(k-changePoint))/255.0;
            Cor[8*i+6] = (68.0+eveB*(k-changePoint))/255.0;
            Cor[8*i+7] = (0.5+eveA*(k-changePoint));
        }
        k++;
    }
    {
        glCullFace(GL_FRONT);
        k=0;
        do
        {
            Ver[4*k] = staDynamic[0][0].usaXCoor[k];
            Ver[4*k+1] = staDynamic[0][0].usaYCoor[k];
            Ver[4*k+2] = staDynamic[1][0].usaXCoor[k];
            Ver[4*k+3] = staDynamic[1][0].usaYCoor[k];
            k++;
        }while(k < 167);
        glVertexAttribPointer(vsLine_position2, 2, GL_FLOAT, GL_FALSE, 0, Ver);
        glVertexAttribPointer(vsLine_color4, 4, GL_FLOAT, GL_FALSE, 0, Cor);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 2*k);
        glCullFace(GL_BACK);
    }


    /* draw filler between left wheel track and left boundary  */
    {
        k=0;
        do
        {
            Ver[4*k] = staDynamic[0][1].usaXCoor[k];
            Ver[4*k+1] = staDynamic[0][1].usaYCoor[k];
            Ver[4*k+2] = staDynamic[1][1].usaXCoor[k];
            Ver[4*k+3] = staDynamic[1][1].usaYCoor[k];
            k++;
        }while(k < 167);
        glVertexAttribPointer(vsLine_position2, 2, GL_FLOAT, GL_FALSE, 0, Ver);
        glVertexAttribPointer(vsLine_color4, 4, GL_FLOAT, GL_FALSE, 0, Cor);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 2*k);
    }

    /* draw filler between right wheel track and left wheel track  */
    glCullFace(GL_FRONT);
    {
        k=0;
        do
        {
#if 1
            if (k<changePoint)
            {
                Cor[8*i] = 68.0/255.0;
                Cor[8*i+1] = 68.0/255.0;
                Cor[8*i+2] = 68.0/255.0;
                Cor[8*i+3] = 0.5;
                Cor[8*i+4] = 68.0/255.0;
                Cor[8*i+5] = 68.0/255.0;
                Cor[8*i+6] = 68.0/255.0;
                Cor[8*i+7] = 0.5;
            }
            else
            {
                Cor[8*i]  = (68.0+eveR*(k-changePoint))/255.0;
                Cor[8*i+1] = (68.0+eveG*(k-changePoint))/255.0;
                Cor[8*i+2] = (68.0+eveB*(k-changePoint))/255.0;
                Cor[8*i+3] = (0.5+eveA*(k-changePoint));
                Cor[8*i+4] = (68.0+eveR*(k-changePoint))/255.0;
                Cor[8*i+5] = (68.0+eveG*(k-changePoint))/255.0;
                Cor[8*i+6] = (68.0+eveB*(k-changePoint))/255.0;
                Cor[8*i+7] = (0.5+eveA*(k-changePoint));
            }
#endif
            Ver[4*k] = staDynamic[2][0].usaXCoor[k];
            Ver[4*k+1] = staDynamic[2][0].usaYCoor[k];
            Ver[4*k+2] = staDynamic[2][1].usaXCoor[k];
            Ver[4*k+3] = staDynamic[2][1].usaYCoor[k];
            k++;
        }while(k < 167);
        glVertexAttribPointer(vsLine_position2, 2, GL_FLOAT, GL_FALSE, 0, Ver);
        glVertexAttribPointer(vsLine_color4, 4, GL_FLOAT, GL_FALSE, 0, Cor);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 2*k);
    }
    glDisable(GL_CULL_FACE);
    /* draw filler between horizontal line and middle filler */
    {
        for (k=0; k<12;k++)
        {
            Cor[4*k] = 68.0/255.0;
            Cor[4*k+1] = 68.0/255.0;
            Cor[4*k+2] = 68.0/255.0;
            Cor[4*k+3] = 0.5;
            Ver[2*k] = stVehicleTracks.backupX[k];
            Ver[2*k+1] = stVehicleTracks.backupY[k];
        }
        glVertexAttribPointer(vsLine_position2, 2, GL_FLOAT, GL_FALSE, 0, Ver);
        glVertexAttribPointer(vsLine_color4, 4, GL_FLOAT, GL_FALSE, 0, Cor);
        glDrawArrays(GL_TRIANGLE_FAN, 0, k);
    }

    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);
    glDisable(GL_BLEND);
    glDisableVertexAttribArray(vsLine_position2);
    glDisableVertexAttribArray(vsLine_color4);
#endif
    glUseProgram(0);
}

void SetMatrix_Tracks(const float *camMatrixBowl, float *projectionBowl)
{
    glUseProgram(obj3DTracks.programObj);
    glUniformMatrix4fv(obj3DTracks.camMatrixLoc,    1, GL_FALSE, camMatrixBowl);
    glUniformMatrix4fv(obj3DTracks.projectionLoc,   1, GL_FALSE, projectionBowl);
    glUseProgram(0);
}

/*frontback: 0--front  1--back*/
static void Dynamic3DTracksRender(LineSegmentLarge staDynamic[][2], int frontback, int apa_switch)
{
    int k = 0,i = 0;
    GLfloat Ver[1200];
    GLfloat Cor[1600];
    GLfloat eveR, eveG, eveB, eveA;
    GLfloat CorR, CorG, CorB, CorA;
    static float APAcorlor[4] = {0.0, 210.0/255.0, 0.0, 1.0};
    static float APAeve[4] = {(132.0-0.0)/199.0, (162.0-255.0)/199.0, (132.0-0.0)/199.0, 0.0};
    static float NOAPAcorlor[4] = {251.0/255.0, 180.0/255.0, 80.0/255.0, 1.0};
    static float NOAPAeve[4] = {(251.0-240.0)/199.0, (180.0-120.0)/199.0, (80.0-0.0)/199.0, 0.0};

    if (1 == apa_switch)
    {
        CorR = APAcorlor[0];
        CorG = APAcorlor[1];
        CorB = APAcorlor[2];
        CorA = APAcorlor[3];

        eveR = APAeve[0];
        eveG = APAeve[1];
        eveB = APAeve[2];
        eveA = APAeve[3];
    }
    else
    {
        CorR = NOAPAcorlor[0];
        CorG = NOAPAcorlor[1];
        CorB = NOAPAcorlor[2];
        CorA = NOAPAcorlor[3];

        eveR = NOAPAeve[0];
        eveG = NOAPAeve[1];
        eveB = NOAPAeve[2];
        eveA = NOAPAeve[3];
    }

    glUseProgram(obj3DTracks.programObj);
    glEnableVertexAttribArray(obj3DTracks.positionLoc3f);
    glEnableVertexAttribArray(obj3DTracks.colorLoc4f);

    glEnable(GL_BLEND);
//    glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);

    glLineWidth(4.0);

    /* draw right three lines and left three lines */
    for (k = 0; k < 200; k++)
    {
        Cor[4*k] = CorR;
        Cor[4*k+1] = CorG;
        Cor[4*k+2] = CorB;
        Cor[4*k+3] = CorA;
    }
    for (i=0;i<3;i++)
    {
        {
            k=0;
            do
            {
                Ver[3*k] = staDynamic[i][0].usaXCoor[k];
                Ver[3*k+1] = lineHeight;
                Ver[3*k+2] = staDynamic[i][0].usaYCoor[k];
                k++;
            }while(k < staDynamic[i][0].ucCount);
            glVertexAttribPointer(obj3DTracks.positionLoc3f, 3, GL_FLOAT, GL_FALSE, 0, Ver);
            glVertexAttribPointer(obj3DTracks.colorLoc4f, 4, GL_FLOAT, GL_FALSE, 0, Cor);
            glDrawArrays(GL_LINE_STRIP, 0, k);
            glDrawArrays(GL_POINTS, 0, k);
        }
        {
            k=0;
            do
            {
                Ver[3*k] = staDynamic[i][1].usaXCoor[k];
                Ver[3*k+1] = lineHeight;
                Ver[3*k+2] = staDynamic[i][1].usaYCoor[k];
                k++;
            }while(k < staDynamic[i][1].ucCount);
            glVertexAttribPointer(obj3DTracks.positionLoc3f, 3, GL_FLOAT, GL_FALSE, 0, Ver);
            glVertexAttribPointer(obj3DTracks.colorLoc4f, 4, GL_FLOAT, GL_FALSE, 0, Cor);
            glDrawArrays(GL_LINE_STRIP, 0, k);
            glDrawArrays(GL_POINTS, 0, k);
        }
    }

    /* draw right wheel track filler */
    for (i = 0, k = 0; i < 200; i++)
    {
        Cor[8*i] = (0+eveR*k)/255.0;
        Cor[8*i+1] = (255.0+eveG*k)/255.0;
        Cor[8*i+2] = (0+eveB*k)/255.0;
        Cor[8*i+3] = (0.3+eveA*k);
        Cor[8*i+4] = (0+eveR*k)/255.0;
        Cor[8*i+5] = (255.0+eveG*k)/255.0;
        Cor[8*i+6] = (0+eveB*k)/255.0;
        Cor[8*i+7] = (0.3+eveA*k);
        k++;
    }
    {
        if (0 == frontback)
            glCullFace(GL_FRONT);
        k=0;
        do
        {
            Ver[6*k] = staDynamic[1][0].usaXCoor[k];
            Ver[6*k+1] = lineHeight;
            Ver[6*k+2] = staDynamic[1][0].usaYCoor[k];
            Ver[6*k+3] = staDynamic[2][0].usaXCoor[k];
            Ver[6*k+4] = lineHeight;
            Ver[6*k+5] = staDynamic[2][0].usaYCoor[k];
            k++;
        }while((k < staDynamic[1][0].ucCount) \
            && (k < staDynamic[2][0].ucCount));
        glVertexAttribPointer(obj3DTracks.positionLoc3f, 3, GL_FLOAT, GL_FALSE, 0, Ver);
        glVertexAttribPointer(obj3DTracks.colorLoc4f, 4, GL_FLOAT, GL_FALSE, 0, Cor);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 2*k);
        if (0 == frontback)
            glCullFace(GL_BACK);
    }

    /* draw left wheel track filler */
    {
        if (1 == frontback)
            glCullFace(GL_FRONT);
        k=0;
        do
        {
            Ver[6*k] = staDynamic[1][1].usaXCoor[k];
            Ver[6*k+1] = lineHeight;
            Ver[6*k+2] = staDynamic[1][1].usaYCoor[k];
            Ver[6*k+3] = staDynamic[2][1].usaXCoor[k];
            Ver[6*k+4] = lineHeight;
            Ver[6*k+5] = staDynamic[2][1].usaYCoor[k];
            k++;
        }while((k < staDynamic[1][1].ucCount) \
            && (k < staDynamic[2][1].ucCount));
        glVertexAttribPointer(obj3DTracks.positionLoc3f, 3, GL_FLOAT, GL_FALSE, 0, Ver);
        glVertexAttribPointer(obj3DTracks.colorLoc4f, 4, GL_FLOAT, GL_FALSE, 0, Cor);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 2*k);
        if (1 == frontback)
            glCullFace(GL_BACK);
    }

    /* draw filler between right wheel track and right boundary  */
    eveR = (130.0-68.0)/199.0;
    eveG = (130.0-68.0)/199.0;
    eveB = (130.0-68.0)/199.0;
    for (i = 0, k = 0; i < 200; i++)
    {
        Cor[8*i] = (68.0+eveR*k)/255.0;
        Cor[8*i+1] = (68.0+eveG*k)/255.0;
        Cor[8*i+2] = (68.0+eveB*k)/255.0;
        Cor[8*i+3] = 0.3;
        Cor[8*i+4] = (68.0+eveR*k)/255.0;
        Cor[8*i+5] = (68.0+eveG*k)/255.0;
        Cor[8*i+6] = (68.0+eveB*k)/255.0;
        Cor[8*i+7] = 0.3;
        k++;
    }
    {
        if (0 == frontback)
            glCullFace(GL_FRONT);
        k=0;
        do
        {
            Ver[6*k] = staDynamic[0][0].usaXCoor[k];
            Ver[6*k+1] = lineHeight;
            Ver[6*k+2] = staDynamic[0][0].usaYCoor[k];
            Ver[6*k+3] = staDynamic[1][0].usaXCoor[k];
            Ver[6*k+4] = lineHeight;
            Ver[6*k+5] = staDynamic[1][0].usaYCoor[k];
            k++;
        }while((k < staDynamic[0][0].ucCount)\
            && (k < staDynamic[1][0].ucCount));
        glVertexAttribPointer(obj3DTracks.positionLoc3f, 3, GL_FLOAT, GL_FALSE, 0, Ver);
        glVertexAttribPointer(obj3DTracks.colorLoc4f, 4, GL_FLOAT, GL_FALSE, 0, Cor);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 2*k);
        if (0 == frontback)
            glCullFace(GL_BACK);
    }

    /* draw filler between left wheel track and left boundary  */
    {
        if (1 == frontback)
            glCullFace(GL_FRONT);
        k=0;
        do
        {
            Ver[6*k] = staDynamic[0][1].usaXCoor[k];
            Ver[6*k+1] = lineHeight;
            Ver[6*k+2] = staDynamic[0][1].usaYCoor[k];
            Ver[6*k+3] = staDynamic[1][1].usaXCoor[k];
            Ver[6*k+4] = lineHeight;
            Ver[6*k+5] = staDynamic[1][1].usaYCoor[k];
            k++;
        }while((k < staDynamic[0][1].ucCount) \
            && (k < staDynamic[1][1].ucCount));
        glVertexAttribPointer(obj3DTracks.positionLoc3f, 3, GL_FLOAT, GL_FALSE, 0, Ver);
        glVertexAttribPointer(obj3DTracks.colorLoc4f, 4, GL_FLOAT, GL_FALSE, 0, Cor);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 2*k);
        if (1 == frontback)
            glCullFace(GL_BACK);
    }

    /* draw filler between right wheel track and left wheel track  */
    {
        if (0 == frontback)
            glCullFace(GL_FRONT);
        k=0;
        do
        {
            Ver[6*k] = staDynamic[2][0].usaXCoor[k];
            Ver[6*k+1] = lineHeight;
            Ver[6*k+2] = staDynamic[2][0].usaYCoor[k];
            Ver[6*k+3] = staDynamic[2][1].usaXCoor[k];
            Ver[6*k+4] = lineHeight;
            Ver[6*k+5] = staDynamic[2][1].usaYCoor[k];
            k++;
        }while((k < staDynamic[2][0].ucCount) \
                && (k < staDynamic[2][1].ucCount));
        glVertexAttribPointer(obj3DTracks.positionLoc3f, 3, GL_FLOAT, GL_FALSE, 0, Ver);
        glVertexAttribPointer(obj3DTracks.colorLoc4f, 4, GL_FLOAT, GL_FALSE, 0, Cor);
        glDrawArrays(GL_TRIANGLE_STRIP, 0, 2*k);
        if (0 == frontback)
            glCullFace(GL_BACK);
    }

//    glEnable(GL_CULL_FACE);
    glCullFace(GL_BACK);
    glDisable(GL_BLEND);
    glDisableVertexAttribArray(obj3DTracks.positionLoc3f);
    glDisableVertexAttribArray(obj3DTracks.colorLoc4f);
    glUseProgram(0);
}


static void leftTracksrender()
{
    GLfloat Ver[6];
    GLfloat Cor[12];
    int k = 0;
    glUseProgram(programLine);
    glEnableVertexAttribArray(vsLine_position2);
    glEnableVertexAttribArray(vsLine_color4);
    glEnable(GL_BLEND);
    glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
    glLineWidth(6.0);

    for (k = 0; k < 3; k++)
    {
        Cor[4*k] = 0.0;
        Cor[4*k+1] = 1.0;
        Cor[4*k+2] = 0.0;
        Cor[4*k+3] = 1.0;
    }
    Ver[0] = g_UndistTrack.Ltrack[0];Ver[1] = g_UndistTrack.Ltrack[1];
    Ver[2] = g_UndistTrack.Ltrack[4];Ver[3] = g_UndistTrack.Ltrack[5];
    Ver[4] = g_UndistTrack.Ltrack[2];Ver[5] = g_UndistTrack.Ltrack[3];
    glVertexAttribPointer(vsLine_position2, 2, GL_FLOAT, GL_FALSE, 0, Ver);
    glVertexAttribPointer(vsLine_color4, 4, GL_FLOAT, GL_FALSE, 0, Cor);
    glDrawArrays(GL_LINE_STRIP, 0, 3);

    for (k = 0; k < 3; k++)
    {
        Cor[4*k] = 1.0;
        Cor[4*k+1] = 1.0;
        Cor[4*k+2] = 0.0;
        Cor[4*k+3] = 1.0;
    }
    Ver[0] = g_UndistTrack.Ltrack[6];Ver[1] = g_UndistTrack.Ltrack[7];
    Ver[2] = g_UndistTrack.Ltrack[4],Ver[3] = g_UndistTrack.Ltrack[5];
    Ver[4] = g_UndistTrack.Ltrack[8],Ver[5] = g_UndistTrack.Ltrack[9];
    glVertexAttribPointer(vsLine_position2, 2, GL_FLOAT, GL_FALSE, 0, Ver);
    glVertexAttribPointer(vsLine_color4, 4, GL_FLOAT, GL_FALSE, 0, Cor);
    glDrawArrays(GL_LINE_STRIP, 0, 3);

    glDisable(GL_BLEND);
    glDisableVertexAttribArray(vsLine_position2);
    glDisableVertexAttribArray(vsLine_color4);
    glUseProgram(0);
}


static void rightTracksrender()
{
    GLfloat Ver[6];
    GLfloat Cor[12];
    int k = 0;
    glUseProgram(programLine);
    glEnableVertexAttribArray(vsLine_position2);
    glEnableVertexAttribArray(vsLine_color4);
    glEnable(GL_BLEND);
    glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
    glLineWidth(6.0);

    for (k = 0; k < 3; k++)
    {
        Cor[4*k] = 0.0;
        Cor[4*k+1] = 1.0;
        Cor[4*k+2] = 0.0;
        Cor[4*k+3] = 1.0;
    }
    Ver[0] = g_UndistTrack.Rtrack[0];Ver[1] = g_UndistTrack.Rtrack[1];
    Ver[2] = g_UndistTrack.Rtrack[4];Ver[3] = g_UndistTrack.Rtrack[5];
    Ver[4] = g_UndistTrack.Rtrack[6];Ver[5] = g_UndistTrack.Rtrack[7];
    glVertexAttribPointer(11, 2, GL_FLOAT, GL_FALSE, 0, Ver);
    glVertexAttribPointer(13, 4, GL_FLOAT, GL_FALSE, 0, Cor);
    glDrawArrays(GL_LINE_STRIP, 0, 3);

    for (k = 0; k < 3; k++)
    {
        Cor[4*k] = 1.0;
        Cor[4*k+1] = 1.0;
        Cor[4*k+2] = 0.0;
        Cor[4*k+3] = 1.0;
    }
    Ver[0] = g_UndistTrack.Rtrack[2];Ver[1] = g_UndistTrack.Rtrack[3];
    Ver[2] = g_UndistTrack.Rtrack[4],Ver[3] = g_UndistTrack.Rtrack[5];
    Ver[4] = g_UndistTrack.Rtrack[8],Ver[5] = g_UndistTrack.Rtrack[9];
    glVertexAttribPointer(vsLine_position2, 2, GL_FLOAT, GL_FALSE, 0, Ver);
    glVertexAttribPointer(vsLine_color4, 4, GL_FLOAT, GL_FALSE, 0, Cor);
    glDrawArrays(GL_LINE_STRIP, 0, 3);

    glDisable(GL_BLEND);
    glDisableVertexAttribArray(vsLine_position2);
    glDisableVertexAttribArray(vsLine_color4);
    glUseProgram(0);
}


static void leftrightTracksrender()
{
    GLfloat Ver[6];
    GLfloat Cor[12];
    int k = 0;
    glUseProgram(programLine);
    glEnableVertexAttribArray(vsLine_position2);
    glEnableVertexAttribArray(vsLine_color4);
    glEnable(GL_BLEND);
    glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE);
    glLineWidth(6.0);

    for (k = 0; k < 3; k++)
    {
        Cor[4*k] = 0.0;
        Cor[4*k+1] = 1.0;
        Cor[4*k+2] = 0.0;
        Cor[4*k+3] = 1.0;
    }
    Ver[0] = g_UndistLRTrack.Ltrack[0];Ver[1] = g_UndistLRTrack.Ltrack[1];
    Ver[2] = g_UndistLRTrack.Ltrack[4];Ver[3] = g_UndistLRTrack.Ltrack[5];
    Ver[4] = g_UndistLRTrack.Ltrack[2];Ver[5] = g_UndistLRTrack.Ltrack[3];
    glVertexAttribPointer(vsLine_position2, 2, GL_FLOAT, GL_FALSE, 0, Ver);
    glVertexAttribPointer(vsLine_color4, 4, GL_FLOAT, GL_FALSE, 0, Cor);
    glDrawArrays(GL_LINE_STRIP, 0, 3);
    for (k = 0; k < 3; k++)
    {
        Cor[4*k] = 1.0;
        Cor[4*k+1] = 1.0;
        Cor[4*k+2] = 0.0;
        Cor[4*k+3] = 1.0;
    }
    Ver[0] = g_UndistLRTrack.Ltrack[6];Ver[1] = g_UndistLRTrack.Ltrack[7];
    Ver[2] = g_UndistLRTrack.Ltrack[4],Ver[3] = g_UndistLRTrack.Ltrack[5];
    Ver[4] = g_UndistLRTrack.Ltrack[8],Ver[5] = g_UndistLRTrack.Ltrack[9];
    glVertexAttribPointer(vsLine_position2, 2, GL_FLOAT, GL_FALSE, 0, Ver);
    glVertexAttribPointer(vsLine_color4, 4, GL_FLOAT, GL_FALSE, 0, Cor);
    glDrawArrays(GL_LINE_STRIP, 0, 3);

    for (k = 0; k < 3; k++)
    {
        Cor[4*k] = 0.0;
        Cor[4*k+1] = 1.0;
        Cor[4*k+2] = 0.0;
        Cor[4*k+3] = 1.0;
    }
    Ver[0] = g_UndistLRTrack.Rtrack[0];Ver[1] = g_UndistLRTrack.Rtrack[1];
    Ver[2] = g_UndistLRTrack.Rtrack[4];Ver[3] = g_UndistLRTrack.Rtrack[5];
    Ver[4] = g_UndistLRTrack.Rtrack[6];Ver[5] = g_UndistLRTrack.Rtrack[7];
    glVertexAttribPointer(vsLine_position2, 2, GL_FLOAT, GL_FALSE, 0, Ver);
    glVertexAttribPointer(vsLine_color4, 4, GL_FLOAT, GL_FALSE, 0, Cor);
    glDrawArrays(GL_LINE_STRIP, 0, 3);

    for (k = 0; k < 3; k++)
    {
        Cor[4*k] = 1.0;
        Cor[4*k+1] = 1.0;
        Cor[4*k+2] = 0.0;
        Cor[4*k+3] = 1.0;
    }
    Ver[0] = g_UndistLRTrack.Rtrack[2];Ver[1] = g_UndistLRTrack.Rtrack[3];
    Ver[2] = g_UndistLRTrack.Rtrack[4],Ver[3] = g_UndistLRTrack.Rtrack[5];
    Ver[4] = g_UndistLRTrack.Rtrack[8],Ver[5] = g_UndistLRTrack.Rtrack[9];
    glVertexAttribPointer(vsLine_position2, 2, GL_FLOAT, GL_FALSE, 0, Ver);
    glVertexAttribPointer(vsLine_color4, 4, GL_FLOAT, GL_FALSE, 0, Cor);
    glDrawArrays(GL_LINE_STRIP, 0, 3);

    glDisable(GL_BLEND);
    glDisableVertexAttribArray(vsLine_position2);
    glDisableVertexAttribArray(vsLine_color4);
    glUseProgram(0);
}


void LineTracksRender(OVSBasicInfo *pOVSBasicInfo_track, enumTracks frontrear, VehicleSignal* pstVehicleSignal)
{
        int angle = pstVehicleSignal->steeringAngle;
        int fr = 0;
        int apa_switch = 0;
        switch(frontrear)
        {
            default:
            case TRACKS_NONE:
                AVM_DEBUG("\033[0;33m This View have no tracks, line:%d\033[0m\n", __LINE__);
                break;
            case TRACKS_CORRECTFRONT:
                GenTrackFrontDynamic(pOVSBasicInfo_track, &stVehicleTracks, angle, fr);
                if (1 == apa_switch)
                {
                    Dynamic2DNoApaTracksrender(stVehicleTracks.staFrontDynamic, &stVehicleTracks.staFrontDynamicS);
                }
                else
                {
                    Dynamic2DApaTracksrender(stVehicleTracks.staFrontDynamic, &stVehicleTracks.staFrontDynamicS);
                }
                break;
            case TRACKS_CORRECTREAR:
                GenTrackRearDynamic(pOVSBasicInfo_track, &stVehicleTracks, angle, fr);
                if (1 == apa_switch)
                {
                    Dynamic2DNoApaTracksrender(stVehicleTracks.staRearDynamic, &stVehicleTracks.staRearDynamicS);
                }
                else
                {
                    Dynamic2DApaTracksrender(stVehicleTracks.staRearDynamic, &stVehicleTracks.staRearDynamicS);
                }
                break;
            case TRACKS_3DTOPVIEW:
                if (1 == pstVehicleSignal->gear)
                {
                    GenFrontTrackDynaBirdImg(pOVSBasicInfo_track, &stBirdviewTrack, angle);
                    Dynamic3DTracksRender(stVehicleTracks.staFrontDynamic, 0, apa_switch);
                }
                else
                {
                    GenRearTrackDynaBirdImg(pOVSBasicInfo_track, &stBirdviewTrack, angle);
                    Dynamic3DTracksRender(stVehicleTracks.staRearDynamic, 1, apa_switch);
                }
                break;
            case TRACKS_CORRECTLEFT:
                leftTracksrender();
                break;
            case TRACKS_CORRECTRIGHT:
                rightTracksrender();
                break;
            case TRACKS_CORRECT_LR_FRONT:
                leftrightTracksrender();
                break;
        }
}

