Home > Enterprise >  OpenGL: Please help me understand this function
OpenGL: Please help me understand this function

Time:12-10

I am trying to understand this function, but I can't seem to follow how this code does its thing.

I am hoping someone can walk me through this so I can understand what's going on.

void mountain::LoadData(const char* heightmap_filename)
{
    heightmap = cv::imread(heightmap_filename, 0);
    heightmap_rows = heightmap.rows;
    heightmap_cols = heightmap.cols;

    for (int i = 0; i < heightmap.rows; i  ) 
        height.push_back(vector<float>(heightmap_cols, 0));

    for (int u = 0; u < heightmap_rows; u  )
    {
        for (int v = 0; v < heightmap_cols; v  )
        {
            height[u][v] = heightmap.at<uchar>(u, v);
            Points.push_back(BROAD_CONTROLLER * (u - 128));
            Points.push_back(BROAD_CONTROLLER * (v - 128));
            Points.push_back(HEIGHT_CONTROLLER * height[u][v]);
            Points.push_back((float)u / 255.);
            Points.push_back((float)v / 255.);
        }
    }

    for (int row = 1; row < heightmap_rows; row  )
    {
        for (int col = 1; col < heightmap_cols; col  )
        {
            indices.push_back((row - 1) * heightmap_cols   col - 1);
            indices.push_back((row - 1) * heightmap_cols   col);
            indices.push_back(row * heightmap_cols   col - 1);
            indices.push_back(row * heightmap_cols   col - 1);
            indices.push_back((row - 1) * heightmap_cols   col);
            indices.push_back(row * heightmap_cols   col);
        }
    }
}

May I know what is the Points vector is inserting?

Points.push_back(BROAD_CONTROLLER * (u - 128));
Points.push_back(BROAD_CONTROLLER * (v - 128));
Points.push_back(HEIGHT_CONTROLLER * height[u][v]);
Points.push_back((float)u / 255.);
Points.push_back((float)v / 255.);

and what is the indices vector is inserting?

indices.push_back((row - 1) * heightmap_cols   col - 1);
indices.push_back((row - 1) * heightmap_cols   col);
indices.push_back(row * heightmap_cols   col - 1);
indices.push_back(row * heightmap_cols   col - 1);
indices.push_back((row - 1) * heightmap_cols   col);
indices.push_back(row * heightmap_cols   col);

This is the function to get silhouette, but I don't get it how does this function work.

void mountain::FindSilhouette()
{
    int count = 0;
    for (int i = 0; i < Points.size() / 5; i  )
    {
        if (abs(Points[5 * i   2] - SEALEVEL) < 2)
        {
            slet buffer(Points[5 * i], Points[5 * i   1], Points[5 * i   2]);
            buffer.num = count;
            silhouette.push_back(buffer);
            count  ;
        }
    }
}

CodePudding user response:

Points.push_back(BROAD_CONTROLLER * (u - 128));
Points.push_back(BROAD_CONTROLLER * (v - 128));
Points.push_back(HEIGHT_CONTROLLER * height[u][v]);
Points.push_back((float)u / 255.);
Points.push_back((float)v / 255.);

Points contains successive groups of 5 floats. The first two are x and y, the two coordinate that the u and v are iterating over. The third one is z, which is looked up in the heightmap (height). The fourth and fifth are most likely uv texture coordinates.

indices.push_back((row - 1) * heightmap_cols   col - 1);
indices.push_back((row - 1) * heightmap_cols   col);
indices.push_back(row * heightmap_cols   col - 1);
indices.push_back(row * heightmap_cols   col - 1); // <- repeats third
indices.push_back((row - 1) * heightmap_cols   col); // <- repeats second
indices.push_back(row * heightmap_cols   col);

The indices are the indices to use to draw two triangles, in this fashion:

0--2
| / 3
|/ /|
1 / |
 4--5

That's why 3 (the fourth) repeats 2 (the third), and 4 repeats 1. heightmap_cols is the number of column in the heightmap, row and col the current position. Basically, it builds a list of indices to lookup the position as the heightmap is drawn as a set of pair of triangles. Each pair forms a square.

CodePudding user response:

May I know what is the Points vector is inserting?

It's effectively inserting a 3D vertex, and a 2D texture coordinate. i.e.

struct Vertex {
  // the 3D position of the vertex
  float x;
  float y;
  float z;
  // the 2D texture coordinate
  float u;
  float u;
};

It generates one of these structures for every single pixel in the input image. I actually think the code is wrong, because it seems to assume images can only ever be 256x256 pixels? I'd probably replace the hardcoded 255 and 128 values with the following:

            // read pixel from image
            height[u][v] = heightmap.at<uchar>(u, v);

            // x & y coordinates 
            Points.push_back(BROAD_CONTROLLER * (u - heightmap_rows/2));
            Points.push_back(BROAD_CONTROLLER * (v - heightmap_cols/2)));
            Points.push_back(HEIGHT_CONTROLLER * height[u][v]);
            Points.push_back((float)u / float(heightmap_rows - 1));
            Points.push_back((float)v / float(heightmap_cols - 1));

That should now work for any image size.

and what is the indices vector is inserting?

indices.push_back((row - 1) * heightmap_cols   col - 1);
indices.push_back((row - 1) * heightmap_cols   col);
indices.push_back(row * heightmap_cols   col - 1);
indices.push_back(row * heightmap_cols   col - 1);
indices.push_back((row - 1) * heightmap_cols   col);
indices.push_back(row * heightmap_cols   col);

To begin with, we now have a 2D grid of vertices (however that has been flattened into a single array - Points). I could here write a simple lambda to convert a 2D index pair (U & V) into a 1D index, which may make it a bit more obvious as to what is happening

auto index = [heightmap_cols](int row, int col) {
  return row * heightmap_cols   col;
};

//   (row-1, col)          (row,   col)
//
//               o---------o
//               |       / |
//               |  2   /  |
//               |     /   |
//               |    /    |
//               |   /  1  |
//               |  /      |
//               | /       |
//               o---------o
// 
//   (row-1, col-1)        (row-1, col-1)

// indices for first triangle
indices.push_back(index(row - 1, col - 1));
indices.push_back(index(row - 1, col    ));
indices.push_back(index(row    , col - 1));

// indices for second triangle
indices.push_back(index(row    , col - 1));
indices.push_back(index(row - 1, col    ));
indices.push_back(index(row    , col    ));

This is the function to get silhouette, but I don't get it how does this function work.

It is creating a new array of points, containing only those points whose height is lower than some threshold (in this case, SEALEVEL and the magic number '2').

if (abs(Points[5 * i   2] - SEALEVEL) < 2)

It's probably a badly named function. findAllPointsUnderwater is probably a better name...

  • Related