I've got some OpenGL code:
void draw_textured_quad(vector<quad> &quads, GLuint shader_program, long signed int x, long signed int y, long signed int tile_size, long signed int win_width, long signed int win_height, GLuint tex_handle, ImVec2 uv_min, ImVec2 uv_max)
{
static GLuint vao = 0, vbo = 0, ibo = 0;
if (!glIsVertexArray(vao))
{
glGenVertexArrays(1, &vao);
glGenBuffers(1, &vbo);
glGenBuffers(1, &ibo);
}
glDisable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
complex<float> v0w(static_cast<float>(x), static_cast<float>(y));
complex<float> v1w(static_cast<float>(x), static_cast<float>(y + tile_size));
complex<float> v2w(static_cast<float>(x + tile_size), static_cast<float>(y + tile_size));
complex<float> v3w(static_cast<float>(x + tile_size), static_cast<float>(y));
v0w.real(v0w.real() * zoom_factor);
v0w.imag(v0w.imag() * zoom_factor);
v1w.real(v1w.real() * zoom_factor);
v1w.imag(v1w.imag() * zoom_factor);
v2w.real(v2w.real() * zoom_factor);
v2w.imag(v2w.imag() * zoom_factor);
v3w.real(v3w.real() * zoom_factor);
v3w.imag(v3w.imag() * zoom_factor);
quad q;
q.vertices[0].x = v0w.real();
q.vertices[0].y = v0w.imag();
q.vertices[1].x = v1w.real();
q.vertices[1].y = v1w.imag();
q.vertices[2].x = v2w.real();
q.vertices[2].y = v2w.imag();
q.vertices[3].x = v3w.real();
q.vertices[3].y = v3w.imag();
quads.push_back(q);
complex<float> v0ndc = get_ndc_coords_from_window_coords(win_width, win_height, v0w);
complex<float> v1ndc = get_ndc_coords_from_window_coords(win_width, win_height, v1w);
complex<float> v2ndc = get_ndc_coords_from_window_coords(win_width, win_height, v2w);
complex<float> v3ndc = get_ndc_coords_from_window_coords(win_width, win_height, v3w);
const GLfloat vertexData[] = {
// X Y Z U V
v0ndc.real(), v0ndc.imag(), 0, uv_min.x, uv_max.y,
v1ndc.real(), v1ndc.imag(), 0, uv_min.x, uv_min.y,
v2ndc.real(), v2ndc.imag(), 0, uv_max.x, uv_min.y,
v3ndc.real(), v3ndc.imag(), 0, uv_max.x, uv_max.y,
};
// https://raw.githubusercontent.com/progschj/OpenGL-Examples/master/03texture.cpp
glBindVertexArray(vao);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * 4 * 5, vertexData, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (char*)0 + 0 * sizeof(GLfloat));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (char*)0 + 3 * sizeof(GLfloat));
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
static const GLuint indexData[] = {
3,1,0,
2,1,3,
};
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(GLuint) * 2 * 3, indexData, GL_STATIC_DRAW);
glBindVertexArray(0);
glUseProgram(ortho_shader.get_program());
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, tex_handle);
glUniform1i(uniforms.ortho_shader_uniforms.tex, 0);
glUniform1i(uniforms.ortho_shader_uniforms.viewport_width, win_width);
glUniform1i(uniforms.ortho_shader_uniforms.viewport_height, win_height);
glBindVertexArray(vao);
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_INT, 0);
}
which is called by this code:
for (size_t i = 0; i < tiles_per_dimension; i++)
{
for (size_t j = 0; j < tiles_per_dimension; j++)
{
size_t index = i * tiles_per_dimension + j;
vector<quad> quads;
draw_textured_quad(quads, ortho_shader.get_program(), int(image_anchor.x) + int(i) * background_tiles[index].tile_size, int(image_anchor.y) + int(j) * background_tiles[index].tile_size, background_tiles[index].tile_size, (int)io.DisplaySize.x, (int)io.DisplaySize.y, my_image_texture, background_tiles[index].uv_min, background_tiles[index].uv_max);
if (quads.size() == 1)
{
int x, y;
SDL_GetMouseState(&x, &y);
quad q = quads[0];
float min_x = FLT_MAX;
float min_y = FLT_MAX;
float max_x = -FLT_MAX;
float max_y = -FLT_MAX;
if (q.vertices[0].x < min_x)
min_x = q.vertices[0].x;
else if (q.vertices[0].x > max_x)
max_x = q.vertices[0].x;
if (q.vertices[1].x < min_x)
min_x = q.vertices[1].x;
else if (q.vertices[1].x > max_x)
max_x = q.vertices[1].x;
if (q.vertices[2].x < min_x)
min_x = q.vertices[2].x;
else if (q.vertices[2].x > max_x)
max_x = q.vertices[2].x;
if (q.vertices[3].x < min_x)
min_x = q.vertices[3].x;
else if (q.vertices[3].x > max_x)
max_x = q.vertices[3].x;
if (q.vertices[0].y < min_y)
min_y = q.vertices[0].y;
else if (q.vertices[0].y > max_y)
max_y = q.vertices[0].y;
if (q.vertices[1].y < min_y)
min_y = q.vertices[1].y;
else if (q.vertices[1].y > max_y)
max_y = q.vertices[1].y;
if (q.vertices[2].y < min_y)
min_y = q.vertices[2].y;
else if (q.vertices[2].y > max_y)
max_y = q.vertices[2].y;
if (q.vertices[3].y < min_y)
min_y = q.vertices[3].y;
else if (q.vertices[3].y > max_y)
max_y = q.vertices[3].y;
if (x >= min_x && x <= max_x && y >= min_y && y <= max_y)
{
cout << i << " " << j << endl;
}
}
}
}
It works perfectly fine when zoom_factor is 1.0. But for other zoom levels, it does not work. Any ideas?
The full source – which requires SDL 2 and OpenCV – is at https://github.com/sjhalayka/tiles