|
|
|
@ -3,12 +3,13 @@ |
|
|
|
#define RENDERER_H |
|
|
|
#define RENDERER_H |
|
|
|
|
|
|
|
|
|
|
|
#include <vector> |
|
|
|
#include <vector> |
|
|
|
|
|
|
|
#include <cmath> // trig functions |
|
|
|
|
|
|
|
#include <cstdlib> // calloc |
|
|
|
|
|
|
|
|
|
|
|
// TODO: decide on extension library
|
|
|
|
// TODO: decide on extension library
|
|
|
|
//#include <GL/glew.h>
|
|
|
|
//#include <GL/glew.h>
|
|
|
|
#include <GL/gl3w.h> |
|
|
|
#include <GL/gl3w.h> |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <SDL2/SDL.h> |
|
|
|
#include <SDL2/SDL.h> |
|
|
|
#include <glm/glm.hpp> |
|
|
|
#include <glm/glm.hpp> |
|
|
|
#include <glm/gtc/matrix_transform.hpp> |
|
|
|
#include <glm/gtc/matrix_transform.hpp> |
|
|
|
@ -17,16 +18,6 @@ |
|
|
|
#include "hexgame.h" |
|
|
|
#include "hexgame.h" |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Interface
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool initRenderer(SDL_Handles &handles, v2i vpDims); |
|
|
|
|
|
|
|
bool createScene(std::vector<hex_info>* hexes); |
|
|
|
|
|
|
|
// TODO: re-implement debug renderer
|
|
|
|
|
|
|
|
void debugRender(HexDrawMode mode, hex_info *startHex, hex_info *currentHex); |
|
|
|
|
|
|
|
void renderFrame(const std::vector<hex_info> *hexes); |
|
|
|
|
|
|
|
void freeBuffers(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const char * VERTEX_SHADER_CODE = |
|
|
|
const char * VERTEX_SHADER_CODE = |
|
|
|
"#version 330 core\n" |
|
|
|
"#version 330 core\n" |
|
|
|
"in vec3 vertexPosition_modelspace;\n" |
|
|
|
"in vec3 vertexPosition_modelspace;\n" |
|
|
|
@ -56,6 +47,13 @@ const char * LINE_FRAGMENT_SHADER_CODE = |
|
|
|
" color = vec3(0,0,0);\n" |
|
|
|
" color = vec3(0,0,0);\n" |
|
|
|
"}"; |
|
|
|
"}"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const char * DEBUG_FRAGMENT_SHADER_CODE = |
|
|
|
|
|
|
|
"#version 330 core\n" |
|
|
|
|
|
|
|
"out vec3 color;\n" |
|
|
|
|
|
|
|
"void main()\n" |
|
|
|
|
|
|
|
"{\n" |
|
|
|
|
|
|
|
" color = vec3(1,0,0);\n" |
|
|
|
|
|
|
|
"}"; |
|
|
|
|
|
|
|
|
|
|
|
typedef struct clear_col |
|
|
|
typedef struct clear_col |
|
|
|
{ |
|
|
|
{ |
|
|
|
@ -91,22 +89,30 @@ typedef struct gl_render_group |
|
|
|
GLuint vertex_array_id; |
|
|
|
GLuint vertex_array_id; |
|
|
|
} gl_render_group; |
|
|
|
} gl_render_group; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
gl_matrix_info g_scene_matrices; |
|
|
|
gl_matrix_info g_scene_matrices; |
|
|
|
gl_render_group g_filled_hex_render_group; |
|
|
|
gl_render_group g_filled_hex_render_group; |
|
|
|
gl_render_group g_hex_line_render_group; |
|
|
|
gl_render_group g_hex_line_render_group; |
|
|
|
|
|
|
|
gl_render_group g_debug_render_group; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Interface
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool initRenderer(SDL_Handles &handles, v2i vpDims); |
|
|
|
|
|
|
|
bool createScene(std::vector<hex_info>* hexes); |
|
|
|
|
|
|
|
void renderFrame(const std::vector<hex_info> *hexes); |
|
|
|
|
|
|
|
void renderDebug(hex_info *start_hex, hex_info * current_hex); |
|
|
|
|
|
|
|
void freeBuffers(); |
|
|
|
|
|
|
|
|
|
|
|
// forward declarations
|
|
|
|
// forward declarations
|
|
|
|
|
|
|
|
|
|
|
|
bool initShaders(GLuint &programID1, GLuint &programID2); |
|
|
|
|
|
|
|
bool initShaderProgram(gl_render_group &rg, const char * vertex_code, const char * frag_code, const char * mat_id); |
|
|
|
bool initShaderProgram(gl_render_group &rg, const char * vertex_code, const char * frag_code, const char * mat_id); |
|
|
|
// enable debug output https://www.khronos.org/opengl/wiki/OpenGL_Error
|
|
|
|
// enable debug output https://www.khronos.org/opengl/wiki/OpenGL_Error
|
|
|
|
void openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, |
|
|
|
void openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, |
|
|
|
GLsizei length, const GLchar* message, const void* userParam); |
|
|
|
GLsizei length, const GLchar* message, const void* userParam); |
|
|
|
void parseHexToGLBuffer(GLfloat buf[], int idx, const hex_info &hex); |
|
|
|
void fillTriangleBufferFromHex(GLfloat buf[], int idx, const hex_info &hex); |
|
|
|
bool fillColorBuffer(GLfloat buf[], int len, std::vector<hex_info> *hexes); |
|
|
|
void fillColorBuffer(GLfloat buf[], int len, std::vector<hex_info> *hexes); |
|
|
|
|
|
|
|
void fillHexLineBuffer(GLfloat buf[], int len, std::vector<hex_info>* hexes); |
|
|
|
bool checkGLBufferSize(GLenum buf_type, int expected_size, int line_num); |
|
|
|
bool checkGLBufferSize(GLenum buf_type, int expected_size, int line_num); |
|
|
|
|
|
|
|
bool initGLBufferObject(gl_buffer* buf_obj, int len, GLenum usage, GLfloat data[]); |
|
|
|
|
|
|
|
|
|
|
|
bool |
|
|
|
bool |
|
|
|
initRenderer(SDL_Handles &handles, v2i vpDims) |
|
|
|
initRenderer(SDL_Handles &handles, v2i vpDims) |
|
|
|
@ -132,11 +138,13 @@ initRenderer(SDL_Handles &handles, v2i vpDims) |
|
|
|
|
|
|
|
|
|
|
|
handles.glContext = SDL_GL_CreateContext(handles.window); |
|
|
|
handles.glContext = SDL_GL_CreateContext(handles.window); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: decide on extension library
|
|
|
|
|
|
|
|
gl3wInit(); |
|
|
|
|
|
|
|
#if 0 |
|
|
|
// Initialize GLEW
|
|
|
|
// Initialize GLEW
|
|
|
|
// glewExperimental is only needed in GLEW <= 1.13.0
|
|
|
|
// glewExperimental is only needed in GLEW <= 1.13.0
|
|
|
|
// we can require version 2.0.0+
|
|
|
|
// we can require version 2.0.0+
|
|
|
|
//glewExperimental = true; // Needed for core profile
|
|
|
|
//glewExperimental = true; // Needed for core profile
|
|
|
|
#if 0 |
|
|
|
|
|
|
|
GLenum err = glewInit(); |
|
|
|
GLenum err = glewInit(); |
|
|
|
if (err != GLEW_OK) { |
|
|
|
if (err != GLEW_OK) { |
|
|
|
LOG(ERROR) << "Failed to initilize GLEW" << glewGetErrorString(err) << "\n"; |
|
|
|
LOG(ERROR) << "Failed to initilize GLEW" << glewGetErrorString(err) << "\n"; |
|
|
|
@ -144,11 +152,6 @@ initRenderer(SDL_Handles &handles, v2i vpDims) |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
// TODO: remove for glew?
|
|
|
|
|
|
|
|
#if 1 |
|
|
|
|
|
|
|
gl3wInit(); |
|
|
|
|
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LOG(INFO) << "opengl vendor: " << glGetString(GL_VENDOR) << "\n"; |
|
|
|
LOG(INFO) << "opengl vendor: " << glGetString(GL_VENDOR) << "\n"; |
|
|
|
LOG(INFO)<< "opengl renderer: " << glGetString(GL_RENDERER) << "\n"; |
|
|
|
LOG(INFO)<< "opengl renderer: " << glGetString(GL_RENDERER) << "\n"; |
|
|
|
LOG(INFO) << "opengl version: " << glGetString(GL_VERSION) << "\n"; |
|
|
|
LOG(INFO) << "opengl version: " << glGetString(GL_VERSION) << "\n"; |
|
|
|
@ -169,8 +172,10 @@ initRenderer(SDL_Handles &handles, v2i vpDims) |
|
|
|
// hide VRAM debug messages
|
|
|
|
// hide VRAM debug messages
|
|
|
|
glDebugMessageControl(GL_DONT_CARE, 33361, GL_DONT_CARE, 0, 0, GL_FALSE); |
|
|
|
glDebugMessageControl(GL_DONT_CARE, 33361, GL_DONT_CARE, 0, 0, GL_FALSE); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: check for errors when compiling shaders
|
|
|
|
initShaderProgram(g_filled_hex_render_group, VERTEX_SHADER_CODE, FRAGMENT_SHADER_CODE, "MVP"); |
|
|
|
initShaderProgram(g_filled_hex_render_group, VERTEX_SHADER_CODE, FRAGMENT_SHADER_CODE, "MVP"); |
|
|
|
initShaderProgram(g_hex_line_render_group, VERTEX_SHADER_CODE, LINE_FRAGMENT_SHADER_CODE, "MVP"); |
|
|
|
initShaderProgram(g_hex_line_render_group, VERTEX_SHADER_CODE, LINE_FRAGMENT_SHADER_CODE, "MVP"); |
|
|
|
|
|
|
|
initShaderProgram(g_debug_render_group, VERTEX_SHADER_CODE, DEBUG_FRAGMENT_SHADER_CODE, "MVP"); |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
@ -201,13 +206,13 @@ initShaderProgram(gl_render_group &rg, const char * vertex_code, const char * fr |
|
|
|
glDeleteShader(vertex_shader_id); |
|
|
|
glDeleteShader(vertex_shader_id); |
|
|
|
glDeleteShader(fragment_shader_id); |
|
|
|
glDeleteShader(fragment_shader_id); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: check for errors when compiling shaders
|
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool |
|
|
|
bool |
|
|
|
createScene(std::vector<hex_info>* hexes) |
|
|
|
createScene(std::vector<hex_info>* hexes) |
|
|
|
{ |
|
|
|
{ |
|
|
|
////////////////////
|
|
|
|
|
|
|
|
// Model, View, Projection Matrices
|
|
|
|
// Model, View, Projection Matrices
|
|
|
|
|
|
|
|
|
|
|
|
// left, right, bottom, top, zNear, zFar
|
|
|
|
// left, right, bottom, top, zNear, zFar
|
|
|
|
@ -222,46 +227,26 @@ createScene(std::vector<hex_info>* hexes) |
|
|
|
g_scene_matrices.model = glm::mat4(1.0f); |
|
|
|
g_scene_matrices.model = glm::mat4(1.0f); |
|
|
|
g_scene_matrices.MVP = g_scene_matrices.projection * g_scene_matrices.view * g_scene_matrices.model;
|
|
|
|
g_scene_matrices.MVP = g_scene_matrices.projection * g_scene_matrices.view * g_scene_matrices.model;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
////////////////////
|
|
|
|
|
|
|
|
// Vertex Data
|
|
|
|
// Vertex Data
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: index duplicate vertices
|
|
|
|
// TODO: index duplicate vertices
|
|
|
|
// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-9-vbo-indexing/
|
|
|
|
// http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-9-vbo-indexing/
|
|
|
|
int hex_count = (int) hexes->size(); |
|
|
|
int hex_count = (int) hexes->size(); |
|
|
|
|
|
|
|
|
|
|
|
gl_buffer *vertex_buffer = &g_filled_hex_render_group.vertex_buffer; |
|
|
|
|
|
|
|
vertex_buffer->buffer_len = hex_count * 6 * 3 * 3; |
|
|
|
|
|
|
|
vertex_buffer->buffer = (GLfloat*) std::calloc(vertex_buffer->buffer_len, sizeof(GLfloat)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 6 triangles * 3 vertices per triangle * 3 floats per vertex = 54
|
|
|
|
// 6 triangles * 3 vertices per triangle * 3 floats per vertex = 54
|
|
|
|
int buf_index = 54; |
|
|
|
int vbuf_len = hex_count * 6 * 3 * 3; |
|
|
|
|
|
|
|
GLfloat vbuf[vbuf_len]; |
|
|
|
for (int i = 0; i < hex_count; i++) |
|
|
|
for (int i = 0; i < hex_count; i++) |
|
|
|
{ |
|
|
|
fillTriangleBufferFromHex(vbuf, 54 * i, (*hexes)[i]); |
|
|
|
parseHexToGLBuffer(vertex_buffer->buffer, buf_index * i, (*hexes)[i]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
glGenBuffers(1, &g_filled_hex_render_group.vertex_buffer.buffer_id); |
|
|
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, g_filled_hex_render_group.vertex_buffer.buffer_id); |
|
|
|
|
|
|
|
glBufferData(GL_ARRAY_BUFFER, vertex_buffer->buffer_len * sizeof(GLfloat), vertex_buffer->buffer, GL_DYNAMIC_DRAW); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!checkGLBufferSize(GL_ARRAY_BUFFER, vertex_buffer->buffer_len * sizeof(GLfloat), __LINE__)) |
|
|
|
if (!initGLBufferObject(&g_filled_hex_render_group.vertex_buffer, vbuf_len, GL_DYNAMIC_DRAW, vbuf)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
// color data for hex vertices
|
|
|
|
// color data for hex vertices
|
|
|
|
|
|
|
|
|
|
|
|
gl_buffer *color_buffer = &g_filled_hex_render_group.color_buffer; |
|
|
|
GLfloat cbuf[vbuf_len]; |
|
|
|
color_buffer->buffer_len = vertex_buffer->buffer_len; |
|
|
|
fillColorBuffer(cbuf, vbuf_len, hexes); |
|
|
|
color_buffer->buffer = (GLfloat*) std::calloc(color_buffer->buffer_len, sizeof(GLfloat)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!fillColorBuffer(color_buffer->buffer, color_buffer->buffer_len, hexes)) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
glGenBuffers(1, &color_buffer->buffer_id); |
|
|
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, color_buffer->buffer_id); |
|
|
|
|
|
|
|
glBufferData(GL_ARRAY_BUFFER, color_buffer->buffer_len * sizeof(GLfloat), color_buffer->buffer, GL_DYNAMIC_DRAW); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!checkGLBufferSize(GL_ARRAY_BUFFER, color_buffer->buffer_len * sizeof(GLfloat), __LINE__)) |
|
|
|
if (!initGLBufferObject(&g_filled_hex_render_group.color_buffer, vbuf_len, GL_DYNAMIC_DRAW, cbuf)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
// hex line vertex data
|
|
|
|
// hex line vertex data
|
|
|
|
@ -270,51 +255,25 @@ createScene(std::vector<hex_info>* hexes) |
|
|
|
// and still use one buffer for multiple shapes/paths gldrawarraysintanced?, gldrawelements?
|
|
|
|
// and still use one buffer for multiple shapes/paths gldrawarraysintanced?, gldrawelements?
|
|
|
|
// https://gamedev.stackexchange.com/questions/104310/opengl-4-5-primitive-restart-vs-base-index
|
|
|
|
// https://gamedev.stackexchange.com/questions/104310/opengl-4-5-primitive-restart-vs-base-index
|
|
|
|
int line_vertices_per_hex = 6 * 2; // 12 vertices since we're using line segments atm
|
|
|
|
int line_vertices_per_hex = 6 * 2; // 12 vertices since we're using line segments atm
|
|
|
|
gl_buffer *line_vertex_buffer = &g_hex_line_render_group.vertex_buffer; |
|
|
|
//gl_buffer *line_vertex_buffer = &g_hex_line_render_group.vertex_buffer;
|
|
|
|
line_vertex_buffer->buffer_len = hexes->size() * line_vertices_per_hex * 3; // 3 floats per vertex
|
|
|
|
int line_buf_len = hexes->size() * line_vertices_per_hex * 3; // 3 floats per vertex
|
|
|
|
line_vertex_buffer->buffer = (GLfloat*) std::calloc(line_vertex_buffer->buffer_len, sizeof(GLfloat)); |
|
|
|
GLfloat line_buf[line_buf_len]; |
|
|
|
|
|
|
|
fillHexLineBuffer(line_buf, line_buf_len, hexes); |
|
|
|
Point p1, p2; |
|
|
|
if (!initGLBufferObject(&g_hex_line_render_group.vertex_buffer, line_buf_len, GL_STATIC_DRAW, line_buf)) |
|
|
|
int line_buf_idx = 0; |
|
|
|
return false; |
|
|
|
for (int i = 0; i < (int) hexes->size(); i++) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
hex_info hxi = (*hexes)[i]; |
|
|
|
|
|
|
|
for (int j = 0; j < 6; j ++) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (j == 5) // wrap
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
p1 = hxi.vertices[j]; |
|
|
|
|
|
|
|
p2 = hxi.vertices[0]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
p1 = hxi.vertices[j]; |
|
|
|
|
|
|
|
p2 = hxi.vertices[j + 1]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
line_vertex_buffer->buffer[line_buf_idx + 0] = p1.x; |
|
|
|
|
|
|
|
line_vertex_buffer->buffer[line_buf_idx + 1] = p1.y; |
|
|
|
|
|
|
|
line_vertex_buffer->buffer[line_buf_idx + 2] = 0.f; |
|
|
|
|
|
|
|
line_vertex_buffer->buffer[line_buf_idx + 3] = p2.x; |
|
|
|
|
|
|
|
line_vertex_buffer->buffer[line_buf_idx + 4] = p2.y; |
|
|
|
|
|
|
|
line_vertex_buffer->buffer[line_buf_idx + 5] = 0.f; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
line_buf_idx += 6; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
glGenBuffers(1, &line_vertex_buffer->buffer_id); |
|
|
|
// debug draw vertexes
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, line_vertex_buffer->buffer_id); |
|
|
|
|
|
|
|
glBufferData(GL_ARRAY_BUFFER, line_vertex_buffer->buffer_len * sizeof(GLfloat), line_vertex_buffer->buffer, GL_STATIC_DRAW); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!checkGLBufferSize(GL_ARRAY_BUFFER, line_vertex_buffer->buffer_len * sizeof(GLfloat), __LINE__)) |
|
|
|
// 4 vertices, 3 floats per vertex
|
|
|
|
|
|
|
|
int len = 4 * 3; |
|
|
|
|
|
|
|
if (!initGLBufferObject(&g_debug_render_group.vertex_buffer, len, GL_DYNAMIC_DRAW, 0)) |
|
|
|
return false; |
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
void |
|
|
|
parseHexToGLBuffer(GLfloat buf[], int idx, const hex_info &hex) |
|
|
|
fillTriangleBufferFromHex(GLfloat buf[], int idx, const hex_info &hex) |
|
|
|
{ |
|
|
|
{ |
|
|
|
// triangles
|
|
|
|
// triangles
|
|
|
|
for (int i = 0; i < 6; i++) |
|
|
|
for (int i = 0; i < 6; i++) |
|
|
|
@ -359,28 +318,9 @@ parseHexToGLBuffer(GLfloat buf[], int idx, const hex_info &hex) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
bool |
|
|
|
void |
|
|
|
fillColorBuffer(GLfloat buf[], int len, std::vector<hex_info>* hexes) |
|
|
|
fillColorBuffer(GLfloat buf[], int len, std::vector<hex_info>* hexes) |
|
|
|
{ |
|
|
|
{ |
|
|
|
if (!buf || len < 1) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
LOG(ERROR) << "buffer length mismatch\n"; |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!hexes || hexes->size() == 0) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
LOG(ERROR) << "hex_info input error\n"; |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 3 floats per vertex, 3 vertexes per triangle, 6 triangles per hex
|
|
|
|
|
|
|
|
if (len != (int) hexes->size() * 3 * 3 * 6) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
LOG(ERROR) << "hex_info input error\n"; |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int buf_idx; |
|
|
|
int buf_idx; |
|
|
|
int buf_len_per_hex = 54; // NOTE: 3 * 3 * 6
|
|
|
|
int buf_len_per_hex = 54; // NOTE: 3 * 3 * 6
|
|
|
|
for (int i = 0; i < (int) hexes->size(); i++) |
|
|
|
for (int i = 0; i < (int) hexes->size(); i++) |
|
|
|
@ -390,12 +330,40 @@ fillColorBuffer(GLfloat buf[], int len, std::vector<hex_info> *hexes) |
|
|
|
GLfloat color = (GLfloat) hxi.current_color / (GLfloat) UINT32_MAX; |
|
|
|
GLfloat color = (GLfloat) hxi.current_color / (GLfloat) UINT32_MAX; |
|
|
|
|
|
|
|
|
|
|
|
for (int j = 0; j < buf_len_per_hex; j++) |
|
|
|
for (int j = 0; j < buf_len_per_hex; j++) |
|
|
|
{ |
|
|
|
|
|
|
|
buf[buf_idx + j] = color; |
|
|
|
buf[buf_idx + j] = color; |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
void |
|
|
|
|
|
|
|
fillHexLineBuffer(GLfloat buf[], int len, std::vector<hex_info>* hexes) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
Point p1, p2; |
|
|
|
|
|
|
|
int idx = 0; |
|
|
|
|
|
|
|
for (int i = 0; i < (int) hexes->size(); i++) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
hex_info hxi = (*hexes)[i]; |
|
|
|
|
|
|
|
for (int j = 0; j < 6; j ++) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (j == 5) // wrap
|
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
p1 = hxi.vertices[j]; |
|
|
|
|
|
|
|
p2 = hxi.vertices[0]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
else |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
p1 = hxi.vertices[j]; |
|
|
|
|
|
|
|
p2 = hxi.vertices[j + 1]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
buf[idx + 0] = p1.x; |
|
|
|
|
|
|
|
buf[idx + 1] = p1.y; |
|
|
|
|
|
|
|
buf[idx + 2] = 0.f; |
|
|
|
|
|
|
|
buf[idx + 3] = p2.x; |
|
|
|
|
|
|
|
buf[idx + 4] = p2.y; |
|
|
|
|
|
|
|
buf[idx + 5] = 0.f; |
|
|
|
|
|
|
|
idx += 6; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// NOTE: this will only work after a call to glBindBuffer
|
|
|
|
// NOTE: this will only work after a call to glBindBuffer
|
|
|
|
@ -414,6 +382,28 @@ checkGLBufferSize(GLenum buf_type, int expected_size, int line_num) |
|
|
|
return true; |
|
|
|
return true; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
|
|
|
initGLBufferObject(gl_buffer* buf_obj, int len, GLenum usage, GLfloat data[]) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
buf_obj->buffer_len = (size_t) len; |
|
|
|
|
|
|
|
buf_obj->buffer = (GLfloat*) std::calloc(len, sizeof(GLfloat)); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (data) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
for (int i = 0; i < len; i++) |
|
|
|
|
|
|
|
buf_obj->buffer[i] = data[i]; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
glGenBuffers(1, &buf_obj->buffer_id); |
|
|
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, buf_obj->buffer_id); |
|
|
|
|
|
|
|
glBufferData(GL_ARRAY_BUFFER, len * sizeof(GLfloat), buf_obj->buffer, usage); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!checkGLBufferSize(GL_ARRAY_BUFFER, len * sizeof(GLfloat), __LINE__)) |
|
|
|
|
|
|
|
return false; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
void |
|
|
|
openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, |
|
|
|
openglDebugCallback(GLenum source, GLenum type, GLuint id, GLenum severity, |
|
|
|
GLsizei length, const GLchar* message, const void* userParam) |
|
|
|
GLsizei length, const GLchar* message, const void* userParam) |
|
|
|
@ -431,7 +421,8 @@ renderFrame(std::vector<hex_info> *hexes) |
|
|
|
glClearColor(g_clear_col.R, g_clear_col.G, g_clear_col.B, g_clear_col.A); |
|
|
|
glClearColor(g_clear_col.R, g_clear_col.G, g_clear_col.B, g_clear_col.A); |
|
|
|
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); |
|
|
|
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// filled hexes
|
|
|
|
|
|
|
|
{ |
|
|
|
// TODO: learn how to use VAOs instead of these calls to glVertexAttribPointer
|
|
|
|
// TODO: learn how to use VAOs instead of these calls to glVertexAttribPointer
|
|
|
|
// https://www.khronos.org/opengl/wiki/Vertex_Specification#Vertex_Array_Object
|
|
|
|
// https://www.khronos.org/opengl/wiki/Vertex_Specification#Vertex_Array_Object
|
|
|
|
gl_render_group* rg = &g_filled_hex_render_group; |
|
|
|
gl_render_group* rg = &g_filled_hex_render_group; |
|
|
|
@ -448,21 +439,23 @@ renderFrame(std::vector<hex_info> *hexes) |
|
|
|
glEnableVertexAttribArray(1); |
|
|
|
glEnableVertexAttribArray(1); |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, rg->color_buffer.buffer_id); |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, rg->color_buffer.buffer_id); |
|
|
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); |
|
|
|
glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); |
|
|
|
|
|
|
|
|
|
|
|
// get new colors every frame
|
|
|
|
// get new colors every frame
|
|
|
|
fillColorBuffer(rg->color_buffer.buffer, rg->color_buffer.buffer_len, hexes); |
|
|
|
fillColorBuffer(rg->color_buffer.buffer, rg->color_buffer.buffer_len, hexes); |
|
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, rg->color_buffer.buffer_len * sizeof(GLfloat), rg->color_buffer.buffer); |
|
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, rg->color_buffer.buffer_len * sizeof(GLfloat), |
|
|
|
|
|
|
|
rg->color_buffer.buffer); |
|
|
|
// draw
|
|
|
|
// draw
|
|
|
|
glDrawArrays(GL_TRIANGLES, 0, rg->vertex_buffer.buffer_len / 3); |
|
|
|
glDrawArrays(GL_TRIANGLES, 0, rg->vertex_buffer.buffer_len / 3); |
|
|
|
|
|
|
|
|
|
|
|
// cleanup
|
|
|
|
// cleanup
|
|
|
|
glDisableVertexAttribArray(0); |
|
|
|
glDisableVertexAttribArray(0); |
|
|
|
glDisableVertexAttribArray(1); |
|
|
|
glDisableVertexAttribArray(1); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// hex lines
|
|
|
|
// hex lines
|
|
|
|
|
|
|
|
// TODO: conpress these calls into helper function
|
|
|
|
rg = &g_hex_line_render_group; |
|
|
|
{ |
|
|
|
|
|
|
|
gl_render_group* rg = &g_hex_line_render_group; |
|
|
|
glUseProgram(rg->program_id); |
|
|
|
glUseProgram(rg->program_id); |
|
|
|
// Send our transformation to the currently bound shader, in the "g_MVP" uniform
|
|
|
|
// Send our transformation to the currently bound shader, in the "g_MVP" uniform
|
|
|
|
glUniformMatrix4fv(rg->matrix_id, 1, GL_FALSE, &g_scene_matrices.MVP[0][0]); |
|
|
|
glUniformMatrix4fv(rg->matrix_id, 1, GL_FALSE, &g_scene_matrices.MVP[0][0]); |
|
|
|
@ -473,57 +466,72 @@ renderFrame(std::vector<hex_info> *hexes) |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_buffer.buffer_id); |
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_buffer.buffer_id); |
|
|
|
glVertexAttribPointer(attrib_index, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); |
|
|
|
glVertexAttribPointer(attrib_index, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); |
|
|
|
glDrawArrays(GL_LINES, 0, rg->vertex_buffer.buffer_len / 3); |
|
|
|
glDrawArrays(GL_LINES, 0, rg->vertex_buffer.buffer_len / 3); |
|
|
|
|
|
|
|
glDisableVertexAttribArray(0); |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
#if 0 |
|
|
|
|
|
|
|
// TODO: many globals used here
|
|
|
|
|
|
|
|
void |
|
|
|
void |
|
|
|
debugRender() |
|
|
|
renderDebug(hex_info *start_hex, hex_info *current_hex) |
|
|
|
{ |
|
|
|
|
|
|
|
if (globalDrawMode == CONE_FILL) |
|
|
|
|
|
|
|
{ |
|
|
|
|
|
|
|
if (startHex && currentHex) |
|
|
|
|
|
|
|
{ |
|
|
|
{ |
|
|
|
Point p1 = hex_to_pixel(global_layout, startHex->hex); |
|
|
|
if (!start_hex || !current_hex) |
|
|
|
Point p2 = hex_to_pixel(global_layout, currentHex->hex); |
|
|
|
return; |
|
|
|
|
|
|
|
|
|
|
|
// NOTE: some cone drawing shenanigans
|
|
|
|
|
|
|
|
real32 angle = (real32) atan2(p2.y - p1.y, p2.x - p1.x); |
|
|
|
|
|
|
|
real32 len = (real32) hypot(p2.y - p1.y, p2.x - p1.x); |
|
|
|
|
|
|
|
real32 coneAngle = 24.5f * (real32) M_PI / 180; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// fill vertex buffer
|
|
|
|
|
|
|
|
Point p1(start_hex->XPos, start_hex->YPos); |
|
|
|
|
|
|
|
Point p2(current_hex->XPos, current_hex->YPos); |
|
|
|
|
|
|
|
real64 angle = std::atan2(p2.y - p1.y, p2.x - p1.x); |
|
|
|
|
|
|
|
real64 len = std::hypot(p2.y - p1.y, p2.x - p1.x); |
|
|
|
|
|
|
|
real64 coneAngle = 24.5f * M_PI / 180; // M_PI is non-standard and may not be portable
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: add matrix math library for rotation transform?
|
|
|
|
// TODO: add matrix math library for rotation transform?
|
|
|
|
// |x| | cos(a + b) -sin(a + b) 0 |
|
|
|
|
// |x| | cos(a + b) -sin(a + b) 0 |
|
|
|
|
// |y| * | sin(a + b) cos(a + b) 0 |
|
|
|
|
// |y| * | sin(a + b) cos(a + b) 0 |
|
|
|
|
// |0| | 0 0 1 |
|
|
|
|
// |0| | 0 0 1 |
|
|
|
|
//
|
|
|
|
//
|
|
|
|
real32 x1 = len * cosf(angle); |
|
|
|
real64 x1 = len * std::cos(angle); |
|
|
|
real32 y1 = len * sinf(angle); |
|
|
|
real64 y1 = len * std::sin(angle); |
|
|
|
// top of cone
|
|
|
|
// top of cone
|
|
|
|
real32 topX = x1 * cosf(coneAngle) - y1 * sinf(coneAngle) + (real32) p1.x; |
|
|
|
real64 topX = x1 * std::cos(coneAngle) - y1 * std::sin(coneAngle) + p1.x; |
|
|
|
real32 topY = x1 * sinf(coneAngle) + y1 * cosf(coneAngle) + (real32) p1.y; |
|
|
|
real64 topY = x1 * std::sin(coneAngle) + y1 * std::cos(coneAngle) + p1.y; |
|
|
|
// bottom of cone
|
|
|
|
// bottom of cone
|
|
|
|
real32 botX = x1 * cosf(coneAngle) + y1 * sinf(coneAngle) + (real32) p1.x; |
|
|
|
real64 botX = x1 * std::cos(coneAngle) + y1 * std::sin(coneAngle) + p1.x; |
|
|
|
real32 botY = x1 * sinf(-1 * coneAngle) + y1 * cosf(coneAngle) + (real32) p1.y; |
|
|
|
real64 botY = x1 * std::sin(-1 * coneAngle) + y1 * std::cos(coneAngle) + p1.y; |
|
|
|
|
|
|
|
// TODO: indexed line drawing
|
|
|
|
glColor4f(1.0f, 1.0f, 0.5f, 1.0f); |
|
|
|
real64 buf[4 * 3] = { |
|
|
|
glLineWidth(1.0f); |
|
|
|
p1.x, p1.y, 0, |
|
|
|
glBegin(GL_LINE_LOOP); |
|
|
|
botX, botY, 0, |
|
|
|
glVertex3d(p1.x, p1.y, 0); |
|
|
|
p2.x, p2.y, 0, |
|
|
|
glVertex3f(botX, botY, 0); |
|
|
|
topX, topY, 0, |
|
|
|
glVertex3d(p2.x, p2.y, 0); |
|
|
|
}; |
|
|
|
glVertex3f(topX, topY, 0); |
|
|
|
|
|
|
|
glEnd(); |
|
|
|
// copy vertexes to render group
|
|
|
|
} |
|
|
|
gl_render_group* rg = &g_debug_render_group; |
|
|
|
} |
|
|
|
for (int i = 0; i < 12; i++) |
|
|
|
|
|
|
|
rg->vertex_buffer.buffer[i] = buf[i]; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TODO: conpress these calls into helper function
|
|
|
|
|
|
|
|
glUseProgram(rg->program_id); |
|
|
|
|
|
|
|
// Send our transformation to the currently bound shader, in the "g_MVP" uniform
|
|
|
|
|
|
|
|
glUniformMatrix4fv(rg->matrix_id, 1, GL_FALSE, &g_scene_matrices.MVP[0][0]); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
glEnableVertexAttribArray(0); |
|
|
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, rg->vertex_buffer.buffer_id); |
|
|
|
|
|
|
|
glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*) 0); |
|
|
|
|
|
|
|
// send new vertex data
|
|
|
|
|
|
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, rg->vertex_buffer.buffer_len * sizeof(GLfloat), |
|
|
|
|
|
|
|
rg->vertex_buffer.buffer); |
|
|
|
|
|
|
|
glDrawArrays(GL_LINE_LOOP, 0, rg->vertex_buffer.buffer_len / 3); |
|
|
|
|
|
|
|
glDisableVertexAttribArray(0); |
|
|
|
} |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void |
|
|
|
void |
|
|
|
freeBuffers() |
|
|
|
freeBuffers() |
|
|
|
{ |
|
|
|
{ |
|
|
|
std::vector<gl_render_group> groups = {g_filled_hex_render_group, g_hex_line_render_group}; |
|
|
|
std::vector<gl_render_group> groups = { |
|
|
|
|
|
|
|
g_filled_hex_render_group, |
|
|
|
|
|
|
|
g_hex_line_render_group, |
|
|
|
|
|
|
|
g_debug_render_group |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
for (gl_render_group group : groups) |
|
|
|
for (gl_render_group group : groups) |
|
|
|
{ |
|
|
|
{ |
|
|
|
|