560 lines
19 KiB
C++
560 lines
19 KiB
C++
// stdlib
|
|
#include <stdio.h>
|
|
|
|
// graphics
|
|
#define GLFW_INCLUDE_NONE
|
|
#include <GLFW/glfw3.h>
|
|
#include "glad.c"
|
|
|
|
#define IMGUI_IMPL_OPENGL_LOADER_CUSTOM
|
|
|
|
#include "imgui/imgui.cpp"
|
|
#include "imgui/imgui_demo.cpp"
|
|
#include "imgui/imgui_draw.cpp"
|
|
#include "imgui/imgui_tables.cpp"
|
|
#include "imgui/imgui_widgets.cpp"
|
|
|
|
#include "imgui/backends/imgui_impl_opengl3.cpp"
|
|
#include "imgui/backends/imgui_impl_glfw.cpp"
|
|
|
|
// fonts
|
|
#include <ft2build.h>
|
|
#include FT_FREETYPE_H
|
|
|
|
// math types
|
|
#include <glm/matrix.hpp>
|
|
#include <glm/gtc/matrix_transform.hpp>
|
|
#include <glm/gtx/vector_angle.hpp>
|
|
#include <glm/gtx/string_cast.hpp>
|
|
|
|
// STL
|
|
#include <iostream>
|
|
|
|
struct charglyph_t {
|
|
uint32_t tex; // handle to glyph texture
|
|
glm::ivec2 size; // 2d dimensions
|
|
glm::ivec2 bearing; // offset from baseline to left/top of glyph
|
|
uint32_t advance; // offset to next glyph
|
|
};
|
|
|
|
struct hex_t {
|
|
glm::vec3 position;
|
|
float radius;
|
|
glm::vec3 vertices[7];
|
|
glm::vec4 color;
|
|
uint32_t vao;
|
|
uint32_t vbo;
|
|
uint32_t ebo;
|
|
};
|
|
|
|
struct grid_t {
|
|
int rows;
|
|
int columns;
|
|
hex_t *hexes;
|
|
};
|
|
|
|
struct camera_t {
|
|
glm::vec3 position;
|
|
glm::vec2 size;
|
|
};
|
|
|
|
charglyph_t glyphmap[128];
|
|
uint32_t text_program;
|
|
uint32_t textvao, textvbo;
|
|
uint32_t hex_program;
|
|
|
|
// error processing
|
|
enum err_type {
|
|
OK = 0,
|
|
ERR_GLFW_INIT,
|
|
ERR_GLFW_WINDOW_CREATION,
|
|
ERR_GLAD_LOAD,
|
|
ERR_FREETYPE_INIT,
|
|
ERR_FONT_INIT,
|
|
ERR_CHAR_LOAD, };
|
|
uint32_t main_errcode = 0;
|
|
const char *errcode_string = "";
|
|
|
|
double mouse_scroll = 0.0;
|
|
|
|
#define MAIN_ERROR(e) do { main_errcode = e; errcode_string = #e; goto exit_main_with_error; } while(0)
|
|
|
|
void glfw_error_callback(int error, const char* description)
|
|
{
|
|
fprintf(stderr, "GLFW error %d: %s\n", error, description);
|
|
}
|
|
|
|
void scroll_callback([[maybe_unused]]GLFWwindow* window, [[maybe_unused]]double xoffset, double yoffset)
|
|
{
|
|
mouse_scroll = yoffset;
|
|
}
|
|
|
|
char* load_file(const char *pathname)
|
|
{
|
|
FILE *text_file = fopen(pathname, "r");
|
|
if (!text_file)
|
|
{
|
|
fprintf(stderr, "Failed trying to read file at %s", pathname);
|
|
return NULL;
|
|
}
|
|
|
|
fseek(text_file, 0, SEEK_END);
|
|
long file_size = ftell(text_file);
|
|
fseek(text_file, 0, SEEK_SET); /* same as rewind(f); */
|
|
|
|
char *file_contents = (char*)calloc(sizeof(char), file_size + 1);
|
|
fread(file_contents, 1, file_size, text_file);
|
|
fclose(text_file);
|
|
return file_contents;
|
|
}
|
|
|
|
uint32_t build_shader_from_source(const char *source, int32_t type)
|
|
{
|
|
char infoLog[512];
|
|
unsigned int shader = glCreateShader(type);
|
|
glShaderSource(shader, 1, (const GLchar * const *)(&source), NULL);
|
|
glCompileShader(shader);
|
|
int success;
|
|
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
|
|
if (!success)
|
|
{
|
|
glGetShaderInfoLog(shader, 512, NULL, infoLog);
|
|
const char *type_str = type == GL_VERTEX_SHADER ? "VERTEX" : "FRAGMENT";
|
|
fprintf(stderr, "Error: %s shader compilation failed: %s\n", type_str, infoLog);
|
|
}
|
|
// TODO: Maybe better error handling?
|
|
return shader;
|
|
}
|
|
|
|
uint32_t make_gl_program(const char *pathname_vertex, const char *pathname_fragment)
|
|
{
|
|
char infoLog[512];
|
|
|
|
char *vertex_source = load_file(pathname_vertex);
|
|
char *fragment_source = load_file(pathname_fragment);
|
|
|
|
unsigned int vertex_shader = build_shader_from_source(vertex_source, GL_VERTEX_SHADER);
|
|
unsigned int fragment_shader = build_shader_from_source(fragment_source, GL_FRAGMENT_SHADER);
|
|
|
|
uint32_t program = glCreateProgram();
|
|
glAttachShader(program, vertex_shader);
|
|
glAttachShader(program, fragment_shader);
|
|
glLinkProgram(program);
|
|
|
|
// print linking errors if any
|
|
int32_t success;
|
|
glGetProgramiv(program, GL_LINK_STATUS, &success);
|
|
if (!success)
|
|
{
|
|
// TODO: Maybe better error handling?
|
|
glGetProgramInfoLog(program, 512, NULL, infoLog);
|
|
fprintf(stderr, "Error: shader linking failed: %s\n", infoLog);
|
|
}
|
|
else
|
|
{
|
|
// Cleanup of unneeded structures
|
|
glDeleteShader(vertex_shader);
|
|
glDeleteShader(fragment_shader);
|
|
}
|
|
return program;
|
|
}
|
|
|
|
void render_text(const char *text, float x, float y, float scale, glm::vec3 color)
|
|
{
|
|
// activate corresponding render state
|
|
glUseProgram(text_program);
|
|
glUniform3f(glGetUniformLocation(text_program, "text_color"), color.x, color.y, color.z);
|
|
glActiveTexture(GL_TEXTURE0);
|
|
glBindVertexArray(textvao);
|
|
|
|
// iterate through 128 ASCI characters
|
|
for (const char *p = text; *p != '\0'; ++p)
|
|
{
|
|
char c = *p;
|
|
charglyph_t charglyph = glyphmap[(size_t)c];
|
|
|
|
float xpos = x + charglyph.bearing.x * scale;
|
|
float ypos = y - (charglyph.size.y - charglyph.bearing.y) * scale;
|
|
|
|
float w = charglyph.size.x * scale;
|
|
float h = charglyph.size.y * scale;
|
|
// update VBO for each character
|
|
float vertices[6][4] = {
|
|
{ xpos, ypos + h, 0.0f, 0.0f },
|
|
{ xpos, ypos, 0.0f, 1.0f },
|
|
{ xpos + w, ypos, 1.0f, 1.0f },
|
|
|
|
{ xpos, ypos + h, 0.0f, 0.0f },
|
|
{ xpos + w, ypos, 1.0f, 1.0f },
|
|
{ xpos + w, ypos + h, 1.0f, 0.0f }
|
|
};
|
|
// render glyph texture over quad
|
|
glBindTexture(GL_TEXTURE_2D, charglyph.tex);
|
|
// update content of VBO memory
|
|
glBindBuffer(GL_ARRAY_BUFFER, textvbo);
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices);
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
// render quad
|
|
glDrawArrays(GL_TRIANGLES, 0, 6);
|
|
// now advance cursors for next glyph (note that advance is number of 1/64 pixels)
|
|
x += (charglyph.advance >> 6) * scale; // bitshift by 6 to get value in pixels (2^6 = 64)
|
|
}
|
|
glBindVertexArray(0);
|
|
glBindTexture(GL_TEXTURE_2D, 0);
|
|
}
|
|
|
|
bool inside_hex(hex_t *hex, glm::vec2 point)
|
|
{
|
|
for (int i = 1; i < 7; ++i)
|
|
{
|
|
glm::vec2 outer_edge = glm::vec2(hex->vertices[(i % 6) +1].x, hex->vertices[(i % 6) + 1].y) - glm::vec2(hex->vertices[i].x, hex->vertices[i].y);
|
|
glm::vec2 inner_vec = glm::vec2(point - glm::vec2(hex->vertices[i].x, hex->vertices[i].y));
|
|
float angle = glm::orientedAngle(glm::normalize(outer_edge), glm::normalize(inner_vec));
|
|
if (angle > 0.0f)
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
// global state
|
|
GLFWwindow *window = nullptr;
|
|
hex_t hexes[4];
|
|
|
|
int main([[maybe_unused]]int argc, [[maybe_unused]]char **argv)
|
|
{
|
|
fprintf(stdout, "Hexnando\n");
|
|
|
|
// Window initialization
|
|
glfwSetErrorCallback(glfw_error_callback);
|
|
if (!glfwInit())
|
|
{
|
|
MAIN_ERROR(ERR_GLFW_INIT);
|
|
}
|
|
|
|
window = glfwCreateWindow(640, 480, "Hexnando", NULL, NULL);
|
|
if (!window)
|
|
{
|
|
MAIN_ERROR(ERR_GLFW_WINDOW_CREATION);
|
|
}
|
|
|
|
glfwMakeContextCurrent(window);
|
|
glfwSetScrollCallback(window, scroll_callback);
|
|
|
|
if (!gladLoadGL())
|
|
{
|
|
MAIN_ERROR(ERR_GLAD_LOAD);
|
|
}
|
|
|
|
int gl_version_major, gl_version_minor;
|
|
glGetIntegerv(GL_MAJOR_VERSION, &gl_version_major);
|
|
glGetIntegerv(GL_MINOR_VERSION, &gl_version_minor);
|
|
|
|
fprintf(stdout, "Using OpenGL %d.%d\n", gl_version_major, gl_version_minor);
|
|
|
|
// font library initialization
|
|
FT_Library ft;
|
|
if (FT_Init_FreeType(&ft))
|
|
{
|
|
MAIN_ERROR(ERR_FREETYPE_INIT);
|
|
}
|
|
|
|
FT_Face face;
|
|
if (FT_New_Face(ft, "fonts/Inconsolata-Regular.ttf", 0, &face))
|
|
{
|
|
MAIN_ERROR(ERR_FONT_INIT);
|
|
}
|
|
|
|
FT_Set_Pixel_Sizes(face, 0, 48);
|
|
|
|
glPixelStorei(GL_UNPACK_ALIGNMENT, 1); // disable byte-alignment restriction
|
|
|
|
for (unsigned char c = 0; c < 128; c++)
|
|
{
|
|
// load character glyph
|
|
if (FT_Load_Char(face, c, FT_LOAD_RENDER))
|
|
{
|
|
MAIN_ERROR(ERR_CHAR_LOAD);
|
|
}
|
|
// generate texture
|
|
uint32_t texture;
|
|
glGenTextures(1, &texture);
|
|
glBindTexture(GL_TEXTURE_2D, texture);
|
|
glTexImage2D(
|
|
GL_TEXTURE_2D,
|
|
0,
|
|
GL_RED,
|
|
face->glyph->bitmap.width,
|
|
face->glyph->bitmap.rows,
|
|
0,
|
|
GL_RED,
|
|
GL_UNSIGNED_BYTE,
|
|
face->glyph->bitmap.buffer
|
|
);
|
|
// set texture options
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
|
// now store character for later use
|
|
charglyph_t charglyph = {
|
|
texture,
|
|
glm::ivec2(face->glyph->bitmap.width, face->glyph->bitmap.rows),
|
|
glm::ivec2(face->glyph->bitmap_left, face->glyph->bitmap_top),
|
|
(uint32_t)face->glyph->advance.x
|
|
};
|
|
glyphmap[c] = charglyph;
|
|
}
|
|
// clear ft2 resources
|
|
FT_Done_Face(face);
|
|
FT_Done_FreeType(ft);
|
|
|
|
// text initialization
|
|
text_program = make_gl_program("shaders/text.vert", "shaders/text.frag");
|
|
|
|
|
|
glGenVertexArrays(1, &textvao);
|
|
glGenBuffers(1, &textvbo);
|
|
glBindVertexArray(textvao);
|
|
glBindBuffer(GL_ARRAY_BUFFER, textvbo);
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 6 * 4, NULL, GL_DYNAMIC_DRAW);
|
|
glEnableVertexAttribArray(0);
|
|
glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 4 * sizeof(float), 0);
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
glBindVertexArray(0);
|
|
|
|
grid_t grid;
|
|
grid.rows = 10;
|
|
grid.columns = 10;
|
|
grid.hexes = (hex_t*)calloc(grid.rows * grid.columns, sizeof(hex_t));
|
|
|
|
|
|
for (int i = 0; i < grid.rows; ++i)
|
|
for (int j = 0; j < grid.columns; ++j)
|
|
{
|
|
hex_t *the_hexagon = &grid.hexes[i*grid.columns+j];
|
|
float radius = 0.2;
|
|
the_hexagon->position = glm::vec3(0,0,0) + glm::vec3(j * radius * 3.0f * glm::cos(glm::radians(60.0))
|
|
, (i * radius * 2.0f * glm::sin(glm::radians(60.0))) + (j % 2 ? 0 : radius * glm::sin(glm::radians(60.0))),
|
|
0);
|
|
the_hexagon->radius = radius;
|
|
the_hexagon->color = glm::vec4(1.0 - i * 0.1, 1.0 - j * 0.1, 1.0, 1.0);
|
|
the_hexagon->vertices[0] = the_hexagon->position;
|
|
the_hexagon->vertices[1] = the_hexagon->position + glm::vec3(-radius, 0, 0);
|
|
the_hexagon->vertices[2] = the_hexagon->position + glm::vec3(-radius * glm::cos(glm::radians(60.0)), radius * glm::sin(glm::radians(60.0)), 0);
|
|
the_hexagon->vertices[3] = the_hexagon->position + glm::vec3(radius * glm::cos(glm::radians(60.0)), radius * glm::sin(glm::radians(60.0)), 0);
|
|
the_hexagon->vertices[4] = the_hexagon->position + glm::vec3(radius, 0, 0);
|
|
the_hexagon->vertices[5] = the_hexagon->position + glm::vec3(radius * glm::cos(glm::radians(60.0)), -radius * glm::sin(glm::radians(60.0)), 0);
|
|
the_hexagon->vertices[6] = the_hexagon->position + glm::vec3(-radius * glm::cos(glm::radians(60.0)), -radius * glm::sin(glm::radians(60.0)), 0);
|
|
|
|
glGenVertexArrays(1, &the_hexagon->vao);
|
|
glGenBuffers(1, &the_hexagon->vbo);
|
|
glBindVertexArray(the_hexagon->vao);
|
|
glBindBuffer(GL_ARRAY_BUFFER, the_hexagon->vbo);
|
|
glBufferData(GL_ARRAY_BUFFER, sizeof(float) * 7 * 3, the_hexagon->vertices, GL_STATIC_DRAW);
|
|
|
|
// EBO setup
|
|
unsigned int indices[18];
|
|
indices[0] = 0; indices[1] = 2; indices[2] = 1;
|
|
indices[3] = 0; indices[4] = 3; indices[5] = 2;
|
|
indices[6] = 0; indices[7] = 4; indices[8] = 3;
|
|
indices[9] = 0; indices[10] = 5; indices[11] = 4;
|
|
indices[12] = 0; indices[13] = 6; indices[14] = 5;
|
|
indices[15] = 0; indices[16] = 1; indices[17] = 6;
|
|
|
|
glGenBuffers(1, &the_hexagon->ebo);
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, the_hexagon->ebo);
|
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 6*3 * sizeof(unsigned int), indices, GL_STATIC_DRAW);
|
|
|
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0);
|
|
glEnableVertexAttribArray(0);
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
glBindVertexArray(0);
|
|
}
|
|
|
|
hex_program = make_gl_program("shaders/hex.vert", "shaders/hex.frag");
|
|
|
|
/* IMGui initalization */
|
|
IMGUI_CHECKVERSION();
|
|
ImGui::CreateContext();
|
|
static ImGuiIO& io = ImGui::GetIO(); (void)io;
|
|
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
|
ImGui::StyleColorsDark();
|
|
ImGui_ImplGlfw_InitForOpenGL(window, true);
|
|
ImGui_ImplOpenGL3_Init("#version 330 core"); // same as shader version
|
|
|
|
double cursor_x;
|
|
double cursor_y;
|
|
camera_t the_camera;
|
|
bool mouse_pressed;
|
|
|
|
the_camera.position = glm::vec3(0.0f, 0.0f, 1.0f);
|
|
the_camera.size = glm::vec2(1.0f, 1.0f);
|
|
// main loop
|
|
while (!glfwWindowShouldClose(window))
|
|
{
|
|
double cursor_dx = 0.0;
|
|
double cursor_dy = 0.0;
|
|
int hovered_hex = -1;
|
|
int32_t window_width, window_height;
|
|
glfwGetWindowSize(window, &window_width, &window_height);
|
|
glViewport(0, 0, window_width, window_height);
|
|
float aspect_ratio = (float)window_width/window_height;
|
|
|
|
/* Input handling */
|
|
if (glfwGetKey(window, GLFW_KEY_W) == GLFW_PRESS)
|
|
the_camera.position.y += 0.1;
|
|
if (glfwGetKey(window, GLFW_KEY_S) == GLFW_PRESS)
|
|
the_camera.position.y -= 0.1;
|
|
if (glfwGetKey(window, GLFW_KEY_A) == GLFW_PRESS)
|
|
the_camera.position.x -= 0.1;
|
|
if (glfwGetKey(window, GLFW_KEY_D) == GLFW_PRESS)
|
|
the_camera.position.x += 0.1;
|
|
if (glfwGetKey(window, GLFW_KEY_R) == GLFW_PRESS)
|
|
the_camera.size -= glm::vec2(0.1);
|
|
if (glfwGetKey(window, GLFW_KEY_F) == GLFW_PRESS)
|
|
the_camera.size += glm::vec2(0.1);
|
|
if (mouse_scroll > 0.0)
|
|
{
|
|
the_camera.size -= glm::vec2(0.1);
|
|
mouse_scroll = 0.0;
|
|
}
|
|
if (mouse_scroll < 0.0)
|
|
{
|
|
the_camera.size += glm::vec2(0.1);
|
|
mouse_scroll = 0.0;
|
|
}
|
|
|
|
mouse_pressed = glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_LEFT) == GLFW_PRESS;
|
|
|
|
// Mouse movement
|
|
if (glfwGetMouseButton(window, GLFW_MOUSE_BUTTON_MIDDLE) == GLFW_PRESS)
|
|
{
|
|
// mouse delta!
|
|
the_camera.position.x += cursor_dx;
|
|
the_camera.position.y += cursor_dy;
|
|
}
|
|
|
|
if (the_camera.size.x < 0.1)
|
|
the_camera.size.x = 0.1;
|
|
if (the_camera.size.y < 0.1)
|
|
the_camera.size.y = 0.1;
|
|
|
|
|
|
cursor_dx = cursor_x;
|
|
cursor_dy = cursor_y;
|
|
|
|
cursor_dx -= cursor_x;
|
|
cursor_dy -= cursor_y;
|
|
glfwGetCursorPos(window, &cursor_x, &cursor_y);
|
|
|
|
/* Rendering */
|
|
glClearColor(0.1f, 0.2f, 0.3f, 1.0f);
|
|
glClear(GL_COLOR_BUFFER_BIT);
|
|
|
|
glm::mat4 model_matrix = glm::mat4(1.0f);
|
|
glm::mat4 view_matrix = glm::mat4(1.0f);
|
|
glm::mat4 proj_matrix = glm::ortho((the_camera.position.x - the_camera.size.x/2) * aspect_ratio, (the_camera.position.x + the_camera.size.x/2) * aspect_ratio, the_camera.position.y - the_camera.size.y/2, the_camera.position.y + the_camera.size.y/2);
|
|
|
|
glm::vec4 aux((float)cursor_x, (float)cursor_y, 0.0f, 1.0f);
|
|
|
|
// move screen coordinates to NDC
|
|
aux.x -= window_width/2.0f;
|
|
aux.x /= window_width/2.0f;
|
|
aux.y -= window_height/2.0f;
|
|
aux.y /= -window_height/2.0f;
|
|
aux = glm::inverse(proj_matrix) * aux;
|
|
glm::vec2 cursor_world = glm::vec2(aux.x, aux.y);
|
|
|
|
glUseProgram(hex_program);
|
|
|
|
glUniformMatrix4fv(glGetUniformLocation(hex_program, "model"), 1, GL_FALSE, &model_matrix[0][0]);
|
|
glUniformMatrix4fv(glGetUniformLocation(hex_program, "view"), 1, GL_FALSE, &view_matrix[0][0]);
|
|
glUniformMatrix4fv(glGetUniformLocation(hex_program, "proj"), 1, GL_FALSE, &proj_matrix[0][0]);
|
|
|
|
for (int i = 0; i < grid.rows; ++i)
|
|
for (int j = 0; j < grid.columns; j++)
|
|
{
|
|
int idx = i * grid.columns + j;
|
|
if (inside_hex(&grid.hexes[idx], cursor_world)) // draw hovered hex differently
|
|
{
|
|
hovered_hex = i * grid.columns + j;
|
|
if (mouse_pressed)
|
|
glUniform4f(glGetUniformLocation(hex_program, "hex_color"), 1.0f, 1.0f, 0.0f, 1.0f);
|
|
else
|
|
glUniform4f(glGetUniformLocation(hex_program, "hex_color"), 1.0f, 0.0f, 0.0f, 1.0f);
|
|
}
|
|
else
|
|
{
|
|
glUniform4f(glGetUniformLocation(hex_program, "hex_color"), grid.hexes[idx].color.x, grid.hexes[idx].color.y, grid.hexes[idx].color.z, grid.hexes[idx].color.w);
|
|
}
|
|
|
|
glBindVertexArray(grid.hexes[idx].vao);
|
|
glBindBuffer(GL_ARRAY_BUFFER, grid.hexes[idx].vbo);
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, grid.hexes[idx].ebo);
|
|
glEnable(GL_CULL_FACE);
|
|
glDrawElements(GL_TRIANGLES, 3*6, GL_UNSIGNED_INT, 0);
|
|
glDisable(GL_CULL_FACE);
|
|
glBindVertexArray(0);
|
|
}
|
|
|
|
glUseProgram(text_program);
|
|
// text rendering
|
|
glEnable(GL_BLEND);
|
|
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
|
|
|
glm::mat4 text_proj_matrix = glm::ortho(0.0f, (float)window_width, 0.0f, (float)window_height);
|
|
glUniformMatrix4fv(glGetUniformLocation(text_program, "projection"), 1, GL_FALSE, &text_proj_matrix[0][0]);
|
|
|
|
static char debug_text_buf[256];
|
|
snprintf(debug_text_buf, 256, "Cursor position %.0f %.0f screen %.2f %.2f world", cursor_x, cursor_y, cursor_world.x, cursor_world.y);
|
|
|
|
render_text(debug_text_buf, 25, 25, .5f, glm::vec3(1.0f, 1.0f, 1.0f));
|
|
|
|
for (int i = 0; i < grid.rows * grid.columns; ++i)
|
|
{
|
|
// Get position of hexes in screen
|
|
glm::vec4 v = glm::vec4(grid.hexes[i].position.x, grid.hexes[i].position.y, grid.hexes[i].position.z, 1.0);
|
|
v = proj_matrix * view_matrix * model_matrix * v;
|
|
v.x += 1;
|
|
v.x *= window_width/2.0f;
|
|
v.y += 1;
|
|
v.y *= window_height/2.0f;
|
|
char number_string[11];
|
|
snprintf(number_string, 11, "%d", i);
|
|
render_text(number_string, v.x, v.y, .2f + (0.3f / the_camera.size.x), glm::vec3(0.0f, 0.0f, 0.0f));
|
|
}
|
|
if (hovered_hex != -1)
|
|
{
|
|
char buf[30];
|
|
snprintf(buf, 30, "Cursor INSIDE hex %d", hovered_hex);
|
|
render_text(buf, 25.0f, window_height - 25.0f, .5f, glm::vec3(1.0f, 1.0f, 1.0f));
|
|
}
|
|
|
|
glDisable(GL_BLEND);
|
|
glfwPollEvents();
|
|
|
|
// Start the Dear ImGui frame
|
|
ImGui_ImplOpenGL3_NewFrame();
|
|
ImGui_ImplGlfw_NewFrame();
|
|
ImGui::NewFrame();
|
|
ImGui::Begin("Hi there");
|
|
ImGui::End();
|
|
ImGui::Render();
|
|
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
|
|
|
glfwSwapBuffers(window);
|
|
}
|
|
|
|
// Cleanup
|
|
ImGui_ImplOpenGL3_Shutdown();
|
|
ImGui_ImplGlfw_Shutdown();
|
|
ImGui::DestroyContext();
|
|
|
|
return 0;
|
|
exit_main_with_error:
|
|
if (window)
|
|
glfwDestroyWindow(window);
|
|
glfwTerminate();
|
|
fprintf(stderr, "Hexnando failed with errcode %d: %s\n", main_errcode, errcode_string);
|
|
return main_errcode;
|
|
}
|