#include "glview.h"
#include <QMatrix4x4>
#include <QDebug>



GLView::GLView(Scene *scene,Camera * camera,Controler *controler,QGLFormat format )
    :QGLWidget(format)
{
    this->camera = camera;
    this->scene = scene;
    this->controler = controler;
    gridSize = 5;
    gridStepSize = 1;
    isGridEnabled = false;
    MIP = false;
    afterInit = false;
    landscape = false;
    if(camera->persp)
        setFocusPolicy(Qt::StrongFocus);
}

void GLView::keyPressEvent(QKeyEvent* event){
    float stepsize = 0.15;
    switch (event->key()) {
    case Qt::Key_W:
        camera->move(QVector3D(0.0,0.0,stepsize));
        break;
    case Qt::Key_S:
        camera->move(QVector3D(0.0,0.0,-stepsize));
        break;

    case Qt::Key_A:
        camera->move(QVector3D(stepsize,0.0,0.0));
        break;
    case Qt::Key_D:
        camera->move(QVector3D(-stepsize,0.0,0.0));
break;
    case Qt::SHIFT:
        camera->move(QVector3D(0.0,stepsize,0.0));
        break;
    default: QWidget::keyPressEvent(event);
    };
    updateGL();
}

QSize GLView::minimumSizeHint() const
{
    return QSize(50, 50);
}

QSize GLView::sizeHint() const
{
    return QSize(600, 400);
}


void GLView::initializeGL ( ) {


    qDebug() << "Current Context:" << this->format();

    Q_ASSERT(initializeOpenGLFunctions());
    qDebug()<<"OpenGL Version"<<this->format().majorVersion()<<this->format().minorVersion();

    glClearColor(0.0, 0.0, 0.0, 0.0);
    glEnable(GL_DEPTH_TEST);


    glEnable(GL_LIGHTING);
    glEnable(GL_LIGHT0);
    static GLfloat lightPosition[4] = { 0.0, 0.0, 4.0, 1.0 };
    glLightfv(GL_LIGHT0, GL_POSITION, lightPosition);


    uchar *trans = new uchar[4*256];

    for(int i = 0; i < 256; i+=1){
        int index = i*4;
        trans[index] = i;
        trans[index+1] = i;
        trans[index+2] = i;
        trans[index+3] = i;
    }

    loadTransfer(trans);

    //Shader Setup
    initShader();
    shader->bind();
    afterInit = true;
}

void GLView::initShader()
{
    QGLShader *vertex = new QGLShader(QGLShader::Vertex);
    if(!vertex->compileSourceFile(QLatin1String(":/phong.vert")))
        qCritical()<< "Vertex Shader failed"<< vertex->log();

    QGLShader *fragment = new QGLShader(QGLShader::Fragment);
    if(!fragment->compileSourceFile(QLatin1String(":/phong.frag")))
        qCritical()<< "Fragment Shader failed"<< fragment->log();

    shader = new QGLShaderProgram(this);
    shader->addShader(vertex);
    shader->addShader(fragment);
    shader->bindAttributeLocation("pickID",4);
    if(!shader->link()){
        qCritical()<< "Linking  failed"<<shader->log();
    }



    vertex = new QGLShader(QGLShader::Vertex);
    if(!vertex->compileSourceFile(QLatin1String(":/display.vert")))
        qCritical()<< "Vertex Shader 2 failed"<< vertex->log();

    fragment = new QGLShader(QGLShader::Fragment);
    if(!fragment->compileSourceFile(QLatin1String(":/display.frag")))
        qCritical()<< "Fragment Shader 2 failed"<< fragment->log();

    displayShader = new QGLShaderProgram(this);
    displayShader->addShader(vertex);
    displayShader->addShader(fragment);
    if(!displayShader->link()){
        qCritical()<< "Linking 2 failed:"<<displayShader->log();
    }

    //landscape
    QOpenGLShader *vertex2 = new QOpenGLShader(QOpenGLShader::Vertex);
    if(!vertex2->compileSourceFile(QLatin1String(":/landscape.vert")))
        qCritical()<< "Vertex Shader landscape failed"<< vertex2->log();

    QOpenGLShader *tesselationControl = new QOpenGLShader(QOpenGLShader::TessellationControl);
    if(!tesselationControl->compileSourceFile(QLatin1String(":/landscape.tcs")))
        qCritical()<< "Tesselation Control landscape failed"<< tesselationControl->log();

    QOpenGLShader *tesselationEval = new QOpenGLShader(QOpenGLShader::TessellationEvaluation);
    if(!tesselationEval->compileSourceFile(QLatin1String(":/landscape.tes")))
        qCritical()<< "Tesselation Eval landscape failed"<< tesselationEval->log();

    QOpenGLShader *geometry = new QOpenGLShader(QOpenGLShader::Geometry);
    if(!geometry->compileSourceFile(QLatin1String(":/landscape.geo")))
        qCritical()<< "Tesselation Eval landscape failed"<< geometry->log();

    QOpenGLShader *fragment2 = new QOpenGLShader(QOpenGLShader::Fragment);
    if(!fragment2->compileSourceFile(QLatin1String(":/landscape.frag")))
        qCritical()<< "Fragment Shader landscape failed"<< fragment2->log();

    landscapeShader = new QOpenGLShaderProgram(this);
    landscapeShader->addShader(vertex2);
    landscapeShader->addShader(fragment2);
    landscapeShader->addShader(tesselationControl);
    landscapeShader->addShader(tesselationEval);
    landscapeShader->addShader(geometry);
    if(!landscapeShader->link()){
        qCritical()<< "Linking landscape failed:"<<landscapeShader->log();
    }




}

void GLView::home(){
    camera->home();
    updateGL();
}

void GLView::setMIP(bool mip){
    this->MIP = mip;
    updateGL();
}



void GLView::paintGL ()
{
    bool useFBO = true;
    //QOpenGLFunctions functions = QOpenGLContext::currentContext()->functions();
    // QGLFunctions functions = QGLFunctions(this->context());



    if(useFBO){
        glBindFramebuffer(GL_FRAMEBUFFER,fbo);
        GLenum buffers[] = {GL_COLOR_ATTACHMENT0,GL_COLOR_ATTACHMENT1,GL_COLOR_ATTACHMENT2,GL_COLOR_ATTACHMENT3};
        glDrawBuffers(4,buffers);

        //http://stackoverflow.com/questions/7207422/setting-up-opengl-multiple-render-targets
    }


    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glEnable(GL_DEPTH_TEST);
    glDisable(GL_CULL_FACE);

    glViewport(0,0,this->width(),this->height());

    glMatrixMode (GL_MODELVIEW);
    glLoadIdentity ();
    glMatrixMode (GL_PROJECTION);
    glLoadIdentity ();
    //set Projection and Camera Rotation
    camera->setupCamera(aspect);


    if(landscape){

//        if(MIP)
//            glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );

        glLineWidth(1);

        float heightScale = 200;
        float horizontalScale = 200;

        landscapeShader->bind();

        landscapeShader->setUniformValue("wireframe",MIP);

        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D,heightmap);
        landscapeShader->setUniformValue("HeightMap",0);

        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D,landscapeTexture1);
        landscapeShader->setUniformValue("landTex1",1);

        glActiveTexture(GL_TEXTURE2);
        glBindTexture(GL_TEXTURE_2D,landscapeTexture2);
        landscapeShader->setUniformValue("landTex2",2);

        landscapeShader->setUniformValue("heightFactor",heightScale);

        //Offset
        QVector3D cam = QVector3D()-*camera->translation;
        cam = camera->rotation->conjugate().rotatedVector(cam); // Cam World Pos
        landscapeShader->setUniformValue("CamPos",cam);

        QVector3D offset = QVector3D(cam);
        offset.setX(ceilf(offset.x()));
        offset.setY(0.0);
        offset.setZ(ceilf(offset.z()));

        QMatrix4x4 offsetM;
        offsetM.translate(offset);
        landscapeShader->setUniformValue("CamOffset",offsetM);

        bool all = false;
        //UV
        QVector2D offsetUV;
        offsetUV.setX(offset.x()/horizontalScale+0.5);
        offsetUV.setY(offset.z()/horizontalScale+0.5);

        if(all){
        offsetUV.setX(0.0);
        offsetUV.setY(0.0);
        }

        QVector2D scaleUV;
        scaleUV.setX( 50/horizontalScale);
        scaleUV.setY( 50/horizontalScale);

        if(all){
            scaleUV.setX( 1.0);
            scaleUV.setY( 1.0);
        }
        landscapeShader->setUniformValue("offsetUV", offsetUV);
        landscapeShader->setUniformValue("scaleUV", scaleUV);



        glBindVertexArray(vertexArray);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER,indices);


        glPatchParameteri(GL_PATCH_VERTICES, 4);
        glDrawElements(GL_PATCHES, IndexCount, GL_UNSIGNED_INT, 0);

        landscapeShader->release();

//        if(MIP)
//            glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );

    }


    shader->bind();
    shader->setUniformValue("shaded",true);

    //draw Scene
    scene->draw(shader);

    shader->setAttributeValue(3,0);

    if(isGridEnabled){
        drawGrid();
    }



    if(isActive){
        glDisable(GL_DEPTH_TEST);
        glMatrixMode (GL_MODELVIEW);
        glLoadIdentity ();
        glMatrixMode (GL_PROJECTION);
        glLoadIdentity ();
        shader->setUniformValue("shaded",false);
        glLineWidth(10);
        GLfloat color[] = {1.0,1.0,0.0};
        glMaterialfv(GL_FRONT,GL_AMBIENT,color);
        glMaterialfv(GL_FRONT,GL_DIFFUSE,color);
        glMaterialfv(GL_FRONT,GL_SPECULAR,color);
        glMaterialf(GL_FRONT,GL_SHININESS,128);

        glBegin (GL_LINE_LOOP);
        glVertex3i (-1, -1, 0);
        glVertex3i (1, -1, 0);
        glVertex3i (1, 1, 0);
        glVertex3i (-1, 1, 0);
        glEnd ();
    }

    shader->release();
    if(useFBO){

        //

        glBindFramebuffer(GL_FRAMEBUFFER,0);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        glViewport(0,0,this->width(),this->height());
        glMatrixMode (GL_MODELVIEW);
        glLoadIdentity ();
        glMatrixMode (GL_PROJECTION);
        glLoadIdentity ();




        displayShader->bind();
        displayShader->setUniformValue("MIP", MIP);

        QMatrix4x4 mat = QMatrix4x4();
        mat.rotate(*camera->rotation);
        displayShader->setUniformValue("NormalMatrix",mat.inverted().transposed());


        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D,color);
        displayShader->setUniformValue("Texture",0);

        glActiveTexture(GL_TEXTURE1);
        glBindTexture(GL_TEXTURE_2D,picID);
        displayShader->setUniformValue("PickID",1);

        glActiveTexture(GL_TEXTURE2);
        glBindTexture(GL_TEXTURE_2D,startRay);
        displayShader->setUniformValue("StartRay",2);

        glActiveTexture(GL_TEXTURE3);
        glBindTexture(GL_TEXTURE_2D,stopRay);
        displayShader->setUniformValue("StopRay",3);

        glActiveTexture(GL_TEXTURE4);
        glBindTexture(GL_TEXTURE_3D,texture3D);
        displayShader->setUniformValue("volumeData",4);

        glActiveTexture(GL_TEXTURE5);
        glBindTexture(GL_TEXTURE_1D,transferFunction);
        displayShader->setUniformValue("transferData",5);

        //displayShader->setUniformValue("active",scene->getActive()->getID());

        glBegin (GL_QUADS);
        glTexCoord2d(0,0);
        glVertex3i (-1, -1, 0);
        glTexCoord2d(1,0);
        glVertex3i (1, -1, 0);
        glTexCoord2d(1,1);
        glVertex3i (1, 1, 0);
        glTexCoord2d(0,1);
        glVertex3i (-1, 1, 0);
        glEnd ();



        displayShader->release();

    }

}


void GLView::drawGrid()
{
    shader->release();

    GLfloat specularColor[] = {0,0,0};
    GLfloat shininess[] = {128};
    glMaterialfv(GL_FRONT,GL_SPECULAR,specularColor);
    glMaterialfv(GL_FRONT,GL_SHININESS, shininess);
    GLfloat grey[] = {1,0.5,0.5};
    glMaterialfv(GL_FRONT,GL_DIFFUSE,grey);
    glNormal3f(0,1,0);

    glDisable(GL_LIGHTING);
    glEnable(GL_COLOR_MATERIAL);

    glLineWidth(1);
    glPolygonMode(GL_FRONT_AND_BACK,GL_LINES);
    glBegin(GL_LINES);
    float stepSize = gridStepSize;
    float x = stepSize;
    float y = stepSize;
    if (stepSize <= 0) stepSize = 1;

    for(; x < gridSize; x += stepSize){
        glVertex3f(x,0,-gridSize);
        glVertex3f(x,0,gridSize);
        glVertex3f(-x,0,-gridSize);
        glVertex3f(-x,0,gridSize);
    }
    for (; y < gridSize; y += stepSize){
        glVertex3f(-gridSize, 0, y);
        glVertex3f(gridSize,0,y);
        glVertex3f(-gridSize,0,-y);
        glVertex3f(gridSize,0,-y);
    }
    glEnd();

    glBegin(GL_LINES);
    x = stepSize;
    y = stepSize;
    if (stepSize <= 0) stepSize = 1;

    for(; x < gridSize; x += stepSize){
        glVertex3f(0,x,-gridSize);
        glVertex3f(0,x,gridSize);
        glVertex3f(0,-x,-gridSize);
        glVertex3f(0,-x,gridSize);
    }
    for (; y < gridSize; y += stepSize){
        glVertex3f(0,-gridSize,  y);
        glVertex3f(0,gridSize,y);
        glVertex3f(0,-gridSize,-y);
        glVertex3f(0,gridSize,-y);
    }
    glEnd();

    glBegin(GL_LINES);
    x = stepSize;
    y = stepSize;
    if (stepSize <= 0) stepSize = 1;

    for(; x < gridSize; x += stepSize){
        glVertex3f(x,-gridSize,0);
        glVertex3f(x,gridSize,0);
        glVertex3f(-x,-gridSize,0);
        glVertex3f(-x,gridSize,0);
    }
    for (; y < gridSize; y += stepSize){
        glVertex3f(-gridSize, y,0);
        glVertex3f(gridSize,y,0);
        glVertex3f(-gridSize,-y,0);
        glVertex3f(gridSize,-y,0);
    }
    glEnd();

    glBegin(GL_LINES);
    glVertex3f(0,0,-gridSize);
    glVertex3f(0,0,gridSize);
    glEnd();
    glBegin(GL_LINES);
    glVertex3f(-gridSize,0,0);
    glVertex3f(gridSize,0,0);
    glEnd();
    glBegin(GL_LINES);
    glVertex3f(0,-gridSize,0);
    glVertex3f(0,gridSize,0);
    glEnd();




    glPolygonMode(GL_FRONT,GL_FILL);
    glEnable(GL_LIGHTING);
    shader->bind();

}

void GLView::resizeGL(int width , int height )
{
    aspect = 1.0*width/height;

    //QGLFunctions functions = QGLFunctions(this->context());
    //QOpenGLFunctions_4_3_Core functions = *this;

    glGenFramebuffers(1, &fbo);
    glBindFramebuffer(GL_FRAMEBUFFER,fbo);



    // Create the color buffer
    glGenTextures(1, &color);
    glBindTexture(GL_TEXTURE_2D, color);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);


    // Create the pcik buffer
    glGenTextures(1, &picID);
    glBindTexture(GL_TEXTURE_2D, picID);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);


    // Create the pcik startRay
    glGenTextures(1, &startRay);
    glBindTexture(GL_TEXTURE_2D, startRay);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

    // Create the pcik stopRay
    glGenTextures(1, &stopRay);
    glBindTexture(GL_TEXTURE_2D, stopRay);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);



    // Create the depth buffer
    glGenRenderbuffers(1, &depth);
    glBindRenderbuffer(GL_RENDERBUFFER, depth);
    glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH_COMPONENT,width,height);

    glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D,color,0);
    glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT1,GL_TEXTURE_2D,picID,0);
    glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT2,GL_TEXTURE_2D,startRay,0);
    glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT3,GL_TEXTURE_2D,stopRay,0);
    glFramebufferRenderbuffer(GL_FRAMEBUFFER,GL_DEPTH_ATTACHMENT,GL_RENDERBUFFER,depth);

    GLenum err = glCheckFramebufferStatus(GL_FRAMEBUFFER);
    if(err == GL_FRAMEBUFFER_COMPLETE){
        // qDebug()<<"FBO OK";
    } else {
        qDebug()<<"FBO ERROR"<<err;
    }

    glBindFramebuffer(GL_FRAMEBUFFER, 0);


}

void GLView::loadData(int width, int height, int depth, char* data, int type  )
{

    glEnable(GL_TEXTURE_3D);
    glGenTextures( 1, &texture3D );
    glBindTexture(GL_TEXTURE_3D, texture3D);

    // Filtering
    glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

    // Wrap
    glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP );
    glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP );
    glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP );

    glTexImage3D( GL_TEXTURE_3D, 0, GL_R8,//
                  width, height, depth,  0,
                  GL_RED,type , data); // Imagedata as ByteBuffer
}

void GLView::setLandscapeTexture(int number, QImage* texture){
    if (texture == NULL){
        return;
    }

    QImage textureImg = QGLWidget::convertToGLFormat( *texture );

    if(number == 1){
        glGenTextures( 1, &landscapeTexture1 );
        glBindTexture( GL_TEXTURE_2D, landscapeTexture1 );

    } else if(number == 2){
        glGenTextures( 1, &landscapeTexture2 );
        glBindTexture( GL_TEXTURE_2D, landscapeTexture2 );

    } else
        qDebug()<<"Error";


    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, textureImg.width(), textureImg.height(), 0, GL_RGBA,
                 GL_UNSIGNED_BYTE, textureImg.bits());

    // Filtering
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

    // Wrap
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT );

    glBindTexture( GL_TEXTURE_2D, 0 );


}

void GLView::setLandscape(int width,int height,int max,boolean shortNeeded,char* data){
    glGenTextures(1,&heightmap);
    glBindTexture(GL_TEXTURE_2D,heightmap);

    // Filtering
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );

    // Wrap
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP );
    glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP );

    int type;

    if(shortNeeded){
        type = GL_SHORT;
    } else
        type = GL_BYTE;

    glTexImage2D(GL_TEXTURE_2D,0,GL_R8,width,height,0,GL_RED,type,data);
    glGenerateMipmap(heightmap);


    const int numberOfQuads = 50;
    const int numberOfVertecies = numberOfQuads+1;
    const float sizeOfQuads = 1.0;

    float offset = (numberOfQuads)/2.0 * sizeOfQuads;
    const int size = numberOfVertecies*numberOfVertecies * 3;
    float vertices[size];

    for (int i = 0; i < numberOfVertecies; ++i) {
        for (int j = 0; j < numberOfVertecies; ++j) {
            int pos = (i*numberOfVertecies+j)*3;

            vertices[pos] = j*sizeOfQuads-offset;
            vertices[pos+2] = i*sizeOfQuads-offset;
            vertices[pos+1] = 0.0;
        }
    }

    //    qDebug()<<"--------------------------------------";
    //    for (int var = 0; var < 51*3; var+=3) {
    //        qDebug()<<var/3<<vertices[var]<<vertices[var+1]<< vertices[var+2];
    //    }

    IndexCount = numberOfQuads*numberOfQuads * 4;
    const int size2 = numberOfQuads*numberOfQuads * 4;
    int indicesI[size2];

    for (int i = 0; i < numberOfQuads; ++i) {
        for (int j = 0; j < numberOfQuads; ++j) {
            int index = (i*numberOfQuads+j);
            int VertexIndex = (i*numberOfVertecies+j);
            indicesI[index*4] = VertexIndex;
            indicesI[index*4+1] = VertexIndex+1;
            indicesI[index*4+2] = VertexIndex+numberOfVertecies+1;
            indicesI[index*4+3] = VertexIndex+numberOfVertecies;
        }
    }

    //    qDebug()<<"--------------------------------------";
    //    for (int var = 50*4*0; var < 50*4*2; var+=4) {
    //        qDebug()<<var/4<<"-"<<indicesI[var]<<indicesI[var+1]<< indicesI[var+2]<< indicesI[var+3];
    //    }

    // Create the vertexArray:
    glGenVertexArrays(1, &vertexArray);
    glBindVertexArray(vertexArray);


    // Create the VBO for positions:
    GLuint positions;
    GLsizei stride = 3 * sizeof(float);
    glGenBuffers(1, &positions);
    glBindBuffer(GL_ARRAY_BUFFER, positions);
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, stride, 0);

    // Create the VBO for indices:

    glGenBuffers(1, &indices);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indicesI), indicesI, GL_STATIC_DRAW);

    //    glDisableVertexAttribArray(0);
    //    glBindVertexArray(0);

    landscape = true;
    updateGL();

}

void GLView::loadTransfer(uchar* data )
{
    //    uchar *test = new uchar[4*256];

    //    for(int i = 0; i< 4*256;i++){
    //       test[i] = data[i];
    //    }
    glGenTextures( 1, &transferFunction );
    glBindTexture(GL_TEXTURE_1D, transferFunction);

    // Filtering
    glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST );
    glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST );

    // Wrap
    glTexParameteri( GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP );

    glTexImage1D(GL_TEXTURE_1D,0,GL_RGBA,256,0,GL_RGBA,GL_UNSIGNED_BYTE,data);
    if(afterInit) updateGL();
}



void GLView::setAcive(bool active)
{
    this->isActive = active;
    updateGL();
}

Camera *GLView::getCamera()
{
    return this->camera;
}


void GLView::mousePressEvent(QMouseEvent *event )
{
    controler->mousePressed(this,event);
}

void GLView::mouseMoveEvent(QMouseEvent *event )
{
    controler->mouseMoveEvent(this,event);
}

void GLView::wheelEvent(QWheelEvent *event )
{
    controler->wheelEvent(this,event);
}

