3

I'm working on making my own topographic map, and I have been using .hgt files from NASA.

I'm loading the files using

void MapImage::load_map_file(const char* filename) {
    std::ifstream file(filename, std::ios::in | std::ios::binary);
    if (!file) {
        std::cout << "Error opening file!" << std::endl;
    }
    std::vector<short> tempHeight(TOTAL_SIZE);
    unsigned char buffer[2];

    int x, y;
    for (int i = 0; i < TOTAL_SIZE; i++) {
        if (!file.read(reinterpret_cast<char*>(buffer), sizeof(buffer))) {
            std::cout << "Error reading file!" << std::endl;
        }
        tempHeight[i] = (buffer[0] << 8) | buffer[1];
    }

    height = tempHeight;
}

And then adding them to an inmemory bitmap using:

void MapImage::loadTextureImage() {
img_tex = 0;
glGenTextures(1, &img_tex);

int x, y, w, h;
w = h = SRTM_SIZE;
unsigned char* img;
img = (unsigned char *)malloc(3 * w * h);
memset(img, 0, sizeof(img));

int g = 0;
double height_color;

/*
for(int i = 0; i < TOTAL_SIZE; i++){
    height_color = (float)height[i] / 10.0;
    g = (height_color * 255);
    if (g>255)g = 255;

    img[i * 3 + 2] = (unsigned char)0;
    img[i * 3 + 1] = (unsigned char)g;
    img[i * 3 + 0]= (unsigned char)0;
}
*/

for (int i = 0; i < w; i++) {
    for (int j = 0; j < h; ++j) {
        x = i; 
        y = (h - 1) - j;

        height_color = (float)height[j + (i * w)] / 10.0;
        g = (height_color * 255);
        if (g>255)g = 255;

        img[(x + y*w) * 3 + 2] = (unsigned char)0;
        img[(x + y*w) * 3 + 1] = (unsigned char)g;
        img[(x + y*w) * 3]     = (unsigned char)0;
    }
}


glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, img_tex);

glTexImage2D(
    GL_TEXTURE_2D,
    0,
    GL_RGB,
    w,
    h,
    0,
    GL_RGB,
    GL_UNSIGNED_BYTE,
    img
);
}

However this results in a image with the corner sliced, like this Sliced image

Using the commented version in the loadTextureImage() looks slightly different, however with the same corner sliced. Sliced image 2

Does anyone have a hint to whats going on? I've tried using a image as a texture, loading with the stbi library, and that works fine, so I'm not sure where it's going wrong.

(the coordinates for the image is N10E099)

Rabbid76
  • 202,892
  • 27
  • 131
  • 174
AlexVestin
  • 2,548
  • 2
  • 16
  • 20

1 Answers1

10

This looks like row misalignment, caused by the 3-wide colour data. Try using the following call just before glTexImage2D:

glPixelStorei(GL_UNPACK_ALIGNMENT, 1);

This alignment value, which is 4 by default, is used by glTexImage2D and friends whenever texture data is read to be sent to the GPU.

There is no verification that it matches what the data actually looks like, so in cases like yours where a row doesn't end on a 4-byte boundary, the first few bytes of the next row will be skipped, leading to this diagonal distortion.

Texture data transfers in the other direction (from the GPU to client memory) are aligned via glPixelStorei(GL_PACK_ALIGNMENT, 1);.

Quentin
  • 62,093
  • 7
  • 131
  • 191
  • @AlexVestin so... Which one was it? Hopefully I will remember it for next time :p – Quentin Aug 03 '17 at 14:20
  • UNPACK_ALIGNMENT is correct, since [The other six of the twelve storage parameters affect how pixel data is read from client memory](https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glPixelStore.xhtml) – Tobias Ribizel Aug 03 '17 at 14:21
  • I will, need a couple more minutes. The first one, glPixelStorei(GL_UNPACK_ALIGNMENT, 1);! – AlexVestin Aug 03 '17 at 14:22
  • @Quentin why did you remove the bottom part!! – Krupip Aug 03 '17 at 14:23
  • @snb well, because that one is for *retrieveing* texture data from the GPU, not sending it (which is the actual issue). I just couldn't remember for sure which was which, so I included both. – Quentin Aug 03 '17 at 14:26
  • @Quentin why did he have to fix alignment in this case? What part would be misaligned? Is the image actually 4 byte? Otherwise it looks like it should have worked given that both device and host are are set to rgb on glTexImage2D. – Krupip Aug 03 '17 at 14:27
  • @snb to be fair I don't know why it has been designed that way. Whatever the source and internal formats are, `glTexImage2D` and friends will try to align rows on 4-byte multiples by default, even if that doesn't match the format width. I find this quite obscure, and lost a good bit of time when it first happened to me. – Quentin Aug 03 '17 at 14:30
  • @Quentin, can you add that to the answer? I know that information would many people headaches in the future. – Krupip Aug 03 '17 at 14:32
  • @snb Good idea, I did just that. – Quentin Aug 03 '17 at 14:37