سؤال

I'm generating a terrain from a .bmp file, as a very early precursor for a strategy game. In my code I load the BMP file as an openGL texture, then using a double loop to generate coordinates (x, y redChannel). Then I create indices by again double looping and generating the triangles for a square between (x,y) to (x+1, y+1). However, when I run the code, I end up with an extra triangle going from the end of one line to the beginning of the next line, and which I cannot seem to solve. This only happens when I use varied heights and a sufficiently large map, or at least it is not visible otherwise.

This is the code:

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);
}

I eventually draw this with this code:

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();
}

Here's a picture of the result:

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

And with only blue lines and black background. http://s21.postimg.org/5yw8sz5mv/triangle_Error_Blue_Line.gif

There also appears to be one of these going in the other direction as well, at the very edge right, but I'm supposing for now that it may be related to the same issue.

هل كانت مفيدة؟

المحلول

I'd simplify this part:

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

The problem looks like topLeft has an extra + 1 when it should only have the + width. This causes the "top" vertices to both be shifted along by one column. You might not notice the offsets within the grid and, as you pointed out, they're not visible until the height changes.

Also, returning new GLsizei(counter) seems a bit round about. Why not just pass in GLsizei& counter.

These might be worth a look too. You can save a fair bit of data using strip primitives for many procedural objects:

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top