openGL drawElements — один дополнительный треугольник с использованием массива индексов?

Я создаю ландшафт из файла .bmp, который является очень ранним предшественником стратегической игры. В моем коде я загружаю файл BMP как текстуру openGL, а затем использую двойной цикл для генерации координат (x, y redChannel). Затем я создаю индексы, снова выполняя двойной цикл и создавая треугольники для квадрата между (x, y) и (x+1, y+1). Однако, когда я запускаю код, я получаю дополнительный треугольник, идущий от конца одной строки к началу следующей строки, который я не могу решить. Это происходит только тогда, когда я использую разную высоту и достаточно большую карту, или, по крайней мере, иначе это не видно.

Это код:

void Map::setupVertices(GLsizei* &sizeP, GLint * &vertexArray, GLubyte* &colorArray){

    //textureNum is the identifier generated by glGenTextures
    GLuint textureNum = loadMap("heightmap.bmp");

    //Bind the texture again, and extract the needed data
    glBindTexture(GL_TEXTURE_2D, textureNum);
    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &width);
    glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &height);
    GLint i = height*width;
    GLubyte * imageData = new GLubyte[i+1];
    glGetTexImage(GL_TEXTURE_2D,0,GL_RED, GL_UNSIGNED_BYTE, &imageData[0]);

    //Setup varibles: counter (used for counting vertices)
    //VertexArray: pointer to address for storing the vertices. Size: 3 ints per point, width*height points total
    //ColorArray: pointer to address for storing the color data. 3 bytes per point.
    int counter = 0;
    vertexArray = new GLint[height*width*3];
    colorArray = new GLubyte[height*width*3];

    srand(time(NULL));
    //Loop through rows
    for (int y = 0; y < height; y++){
        //Loop along the line
        for (int x=0; x < width; x++){
            //Add vertices: x, y, redChannel
            //Add colordata: the common-color.
            colorArray[counter] = imageData[x+y*width];
            vertexArray[counter++] = x;
            colorArray[counter] = imageData[x+y*width];
            vertexArray[counter++] = y;
            colorArray[counter] =  imageData[x+y*width];//(float) (rand() % 255);
            vertexArray[counter++] = (float)imageData[x+y*width] /255 * maxHeight;
        }
    }
    //"Return" total vertice amount
    sizeP = new GLsizei(counter);

}

void Map::setupIndices(GLsizei* &sizeP, GLuint* &indexArray){
    //Pointer to location for storing indices. Size: 2 triangles per square, 3 points per triangle, width*height triangles
    indexArray = new GLuint[width*height*2*3];
    int counter = 0;
    //Loop through rows, don't go to top row (because those triangles are to the row below)
    for (int y = 0; y < height-1; y++){
        //Loop along the line, don't go to last point (those are connected to second last point)
        for (int x=0; x < width-1; x++){
            //
            //  TL___TR
            //  |  /  |
            //  LL___LR
             int lowerLeft = x + width*y;
             int lowerRight = lowerLeft+1;
             int topLeft = lowerLeft + width+1;
             int topRight =  topLeft + 1;

             indexArray[counter++] = lowerLeft;
             indexArray[counter++] = lowerRight;
             indexArray[counter++] = topLeft;

             indexArray[counter++] = topLeft;
             indexArray[counter++] = lowerRight;
             indexArray[counter++] = topRight;
        }
    }
    //"Return" the amount of indices
    sizeP = new GLsizei(counter);
}

В конце концов я нарисовал это с помощью этого кода:

void drawGL(){
    glPushMatrix();
    glEnableClientState(GL_VERTEX_ARRAY);
    glVertexPointer(3,GL_INT,0,mapHeight);
    glEnableClientState(GL_COLOR_ARRAY);
    glColorPointer(3,GL_UNSIGNED_BYTE,0,mapcolor);
    if (totalIndices != 0x00000000){
        glDrawElements(GL_TRIANGLES, *totalIndices, GL_UNSIGNED_INT, indices);
    glDisableClientState(GL_VERTEX_ARRAY);
    glDisableClientState(GL_COLOR_ARRAY);
    glPopMatrix();
}

Вот фото результата:

http://s22.postimg.org/k2qoru3kx/open_GLtriangles.gif

И только с синими линиями и черным фоном. http://s21.postimg.org/5yw8sz5mv/triangle_Error_Blue_Line.gif

Также кажется, что один из них движется в другом направлении, на самом краю справа, но я предполагаю, что это может быть связано с той же проблемой.


person Tom Olsson    schedule 23.10.2013    source источник
comment
int topLeft = нижний левый + ширина+1; Это +1 правильно?   -  person Sarien    schedule 23.10.2013
comment
О! Я, должно быть, сто раз смотрел на это, не замечая. Большое спасибо!   -  person Tom Olsson    schedule 23.10.2013


Ответы (1)


Я бы упростил эту часть:

         int lowerLeft = x + width * y;
         int lowerRight = (x + 1) + width * y;
         int topLeft = x + width * (y + 1);
         int topRight = (x + 1) + width * (y + 1);

Проблема выглядит так, что topLeft имеет дополнительный + 1, хотя должен иметь только + width. Это приводит к смещению "верхних" вершин на один столбец. Вы можете не заметить смещения внутри сетки, и, как вы указали, они не видны до тех пор, пока не изменится высота.

Кроме того, возвращение new GLsizei(counter) кажется немного странным. Почему бы просто не передать GLsizei& counter.

Эти, возможно, тоже стоит посмотреть. Вы можете сохранить немало данных, используя примитивы полосы для многих процедурных объектов:

person jozxyqk    schedule 23.10.2013