|
|
|
|
@ -7,15 +7,20 @@
|
|
|
|
|
// forward declarations
|
|
|
|
|
hex_info createHexInfo(hexgrid& hg, int q, int r); |
|
|
|
|
void createHexagonGrid(hexgrid& hg); |
|
|
|
|
bool incrementGLBufferCount(render_group* rg, uint len); |
|
|
|
|
void insertHexVertexData(render_group* rg_filled, render_group* rg_lines, hex_info& hxi); |
|
|
|
|
void populateFilledHexGLBuffers(hexgrid& hg, hex_info& hxi, render_group* rg_filled); |
|
|
|
|
void populateLineGLBuffers(hexgrid& hg, hex_info& hxi, render_group* rg_lines); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// interface
|
|
|
|
|
|
|
|
|
|
// TODO: testing add/remove hex interface
|
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
hgCreateHexes(hexgrid& hg) |
|
|
|
|
hgInit(hexgrid& hg, render_group* rg_filled, render_group* rg_lines) |
|
|
|
|
{ |
|
|
|
|
Orientation o = (hg.layout_mode == LAYOUT_FLAT) ? layout_flat : layout_pointy; |
|
|
|
|
hg.hexlib_layout = Layout(o, Point(hg.hex_size, hg.hex_size), Point(hg.position.x, hg.position.y)); |
|
|
|
|
|
|
|
|
|
if (hg.gridT == HEXAGON) { |
|
|
|
|
createHexagonGrid(hg); |
|
|
|
|
} else { |
|
|
|
|
@ -23,37 +28,94 @@ hgCreateHexes(hexgrid& hg)
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint hex_count = hg.hex_map.size(); |
|
|
|
|
assert(hex_count < MAX_HEX_COUNT); |
|
|
|
|
|
|
|
|
|
render_object* ro_f = rg_filled->render_objects[0]; |
|
|
|
|
render_object* ro_l = rg_lines->render_objects[0]; |
|
|
|
|
ro_f->vertex_buffer.count = hex_count * IDX_PER_HEX_FILLED; |
|
|
|
|
ro_f->normal_buffer.count = hex_count * IDX_PER_HEX_FILLED; |
|
|
|
|
ro_f->uv_buffer.count = hex_count * IDX_PER_HEX_FILLED; |
|
|
|
|
ro_l->vertex_buffer.count = hex_count * IDX_PER_HEX_LINES; |
|
|
|
|
ro_l->normal_buffer.count = hex_count * IDX_PER_HEX_LINES; |
|
|
|
|
ro_l->uv_buffer.count = hex_count * IDX_PER_HEX_LINES; |
|
|
|
|
ro_f->use_texture = true; |
|
|
|
|
ro_l->use_texture = true; |
|
|
|
|
|
|
|
|
|
// populate buffers
|
|
|
|
|
for (auto it : hg.hex_map) { |
|
|
|
|
populateFilledHexGLBuffers(hg, it.second, rg_filled); |
|
|
|
|
populateLineGLBuffers(hg, it.second, rg_lines); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// send buffers to GL
|
|
|
|
|
rgBufferData(&ro_f->vertex_buffer, GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER); |
|
|
|
|
rgBufferData(&ro_f->normal_buffer, GL_STATIC_DRAW, GL_ARRAY_BUFFER); |
|
|
|
|
rgBufferData(&ro_f->uv_buffer, GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER); |
|
|
|
|
rgBufferData(&ro_l->vertex_buffer, GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER); |
|
|
|
|
rgBufferData(&ro_l->normal_buffer, GL_STATIC_DRAW, GL_ARRAY_BUFFER); |
|
|
|
|
rgBufferData(&ro_l->uv_buffer, GL_DYNAMIC_DRAW, GL_ARRAY_BUFFER); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// TODO: testing add/remove hex interface
|
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
hgAddHex(hexgrid& hg, v3f hex_coords, render_group* rg_filled, render_group* rg_lines) |
|
|
|
|
{ |
|
|
|
|
hex_info* hxi = hgGetSingleHex(hg, hex_coords.x, hex_coords.y); |
|
|
|
|
if (hxi) { |
|
|
|
|
hxi->selected = true; |
|
|
|
|
return false; |
|
|
|
|
} else { |
|
|
|
|
Hex h = hex_round(pixel_to_hex(hg.hexlib_layout, Point(hex_coords.x, hex_coords.y))); |
|
|
|
|
hex_info new_hex = createHexInfo(hg, h.q, h.r); |
|
|
|
|
// TODO: need to reseize the GL buffers for filled hexes & hex lines here
|
|
|
|
|
|
|
|
|
|
uint filled_increment = 54; |
|
|
|
|
uint lines_increment = 36; |
|
|
|
|
|
|
|
|
|
if (incrementGLBufferCount(rg_filled, filled_increment) && |
|
|
|
|
incrementGLBufferCount(rg_lines, lines_increment)) |
|
|
|
|
if (!hxi) { |
|
|
|
|
// sanity checks
|
|
|
|
|
render_object* ro_f = rg_filled->render_objects[0]; |
|
|
|
|
gl_buffer& vb_f = ro_f->vertex_buffer; |
|
|
|
|
gl_buffer& nb_f = ro_f->normal_buffer; |
|
|
|
|
gl_buffer& ub_f = ro_f->uv_buffer; |
|
|
|
|
render_object* ro_l = rg_lines->render_objects[0]; |
|
|
|
|
gl_buffer& vb_l = ro_l->vertex_buffer; |
|
|
|
|
gl_buffer& nb_l = ro_l->normal_buffer; |
|
|
|
|
gl_buffer& ub_l = ro_l->uv_buffer; |
|
|
|
|
|
|
|
|
|
if (vb_f.count + IDX_PER_HEX_FILLED < vb_f.max_count && |
|
|
|
|
nb_f.count + IDX_PER_HEX_FILLED < nb_f.max_count && |
|
|
|
|
ub_f.count + IDX_PER_HEX_FILLED < ub_f.max_count && |
|
|
|
|
vb_l.count + IDX_PER_HEX_LINES < vb_l.max_count && |
|
|
|
|
nb_l.count + IDX_PER_HEX_LINES < nb_l.max_count && |
|
|
|
|
ub_l.count + IDX_PER_HEX_LINES < ub_l.max_count) |
|
|
|
|
{ |
|
|
|
|
insertHexVertexData(rg_filled, rg_lines, new_hex); |
|
|
|
|
vb_f.count += IDX_PER_HEX_FILLED; |
|
|
|
|
nb_f.count += IDX_PER_HEX_FILLED; |
|
|
|
|
ub_f.count += IDX_PER_HEX_FILLED; |
|
|
|
|
vb_l.count += IDX_PER_HEX_LINES; |
|
|
|
|
nb_l.count += IDX_PER_HEX_LINES; |
|
|
|
|
ub_l.count += IDX_PER_HEX_LINES; |
|
|
|
|
|
|
|
|
|
Hex h = hex_round(pixel_to_hex(hg.hexlib_layout, Point(hex_coords.x, hex_coords.y))); |
|
|
|
|
hex_info new_hex = createHexInfo(hg, h.q, h.r); |
|
|
|
|
hg.hex_map.insert({h, new_hex}); |
|
|
|
|
populateFilledHexGLBuffers(hg, new_hex, rg_filled); |
|
|
|
|
populateLineGLBuffers(hg, new_hex, rg_lines); |
|
|
|
|
|
|
|
|
|
// NOTE: we could send just a part of the buffer if performance ends up being bad here
|
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, vb_f.buffer_id); |
|
|
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, vb_f.count * sizeof(GLfloat), vb_f.buffer); |
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, nb_f.buffer_id); |
|
|
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, nb_f.count * sizeof(GLfloat), nb_f.buffer); |
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, ub_f.buffer_id); |
|
|
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, ub_f.count * sizeof(GLfloat), ub_f.buffer); |
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, vb_l.buffer_id); |
|
|
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, vb_l.count * sizeof(GLfloat), vb_l.buffer); |
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, nb_l.buffer_id); |
|
|
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, nb_l.count * sizeof(GLfloat), nb_l.buffer); |
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, ub_l.buffer_id); |
|
|
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, ub_l.count * sizeof(GLfloat), ub_l.buffer); |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} else { |
|
|
|
|
LOG(ERROR) << "Attempting to add hex failed\n"; |
|
|
|
|
LOG(ERROR) << "that hex isn't going to fit in the buffer(s)\n"; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
@ -178,17 +240,14 @@ hgUpdateHexConeFill(hexgrid& hg, int32 x, int32 y, float cone_angle, std::vector
|
|
|
|
|
void |
|
|
|
|
hgUpdateUVBuffer(hexgrid& hg, float* uv_buffer, uint buf_len) |
|
|
|
|
{ |
|
|
|
|
// NOTE: 6 triangles * 3 vertices * 3 floats (not 2 to stay aligned with vbuffer)
|
|
|
|
|
uint buf_len_per_hex = 54; |
|
|
|
|
|
|
|
|
|
assert(buf_len == hg.hex_map.size() * buf_len_per_hex); |
|
|
|
|
assert(buf_len == hg.hex_map.size() * IDX_PER_HEX_FILLED); |
|
|
|
|
|
|
|
|
|
for (auto& it : hg.hex_map) { |
|
|
|
|
hex_info hxi = it.second; |
|
|
|
|
v2f uv_coords = (hxi.selected) ? hg.selected_fill_color_uv : hg.fill_color_uv; |
|
|
|
|
uint buf_idx = hxi.hexID * buf_len_per_hex; |
|
|
|
|
uint buf_idx = hxi.hexID * IDX_PER_HEX_FILLED; |
|
|
|
|
|
|
|
|
|
for (uint j = 0; j < buf_len_per_hex; j +=3) { |
|
|
|
|
for (uint j = 0; j < IDX_PER_HEX_FILLED; j +=3) { |
|
|
|
|
uv_buffer[buf_idx + j + 0] = uv_coords.x; |
|
|
|
|
uv_buffer[buf_idx + j + 1] = uv_coords.y; |
|
|
|
|
uv_buffer[buf_idx + j + 2] = 0; |
|
|
|
|
@ -238,82 +297,90 @@ createHexagonGrid(hexgrid& hg)
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool |
|
|
|
|
incrementGLBufferCount(render_group* rg, uint len) |
|
|
|
|
void |
|
|
|
|
populateFilledHexGLBuffers(hexgrid& hg, hex_info& hxi, render_group* rg_filled) |
|
|
|
|
{ |
|
|
|
|
render_object* ro = rg->render_objects[0]; |
|
|
|
|
gl_buffer& vb = ro->vertex_buffer; |
|
|
|
|
gl_buffer& nb = ro->normal_buffer; |
|
|
|
|
gl_buffer& ub = ro->uv_buffer; |
|
|
|
|
|
|
|
|
|
if (vb.count + len <= vb.max_count && |
|
|
|
|
nb.count + len <= nb.max_count && |
|
|
|
|
ub.count + len <= ub.max_count) |
|
|
|
|
{ |
|
|
|
|
vb.count += len; |
|
|
|
|
nb.count += len; |
|
|
|
|
ub.count += len; |
|
|
|
|
|
|
|
|
|
return true; |
|
|
|
|
} else { |
|
|
|
|
return false; |
|
|
|
|
render_object* ro = rg_filled->render_objects[0]; |
|
|
|
|
gl_buffer& vbuf = ro->vertex_buffer; |
|
|
|
|
gl_buffer& normal_buf = ro->normal_buffer; |
|
|
|
|
gl_buffer& uv_buf = ro->uv_buffer; |
|
|
|
|
uint idx = hxi.hexID * IDX_PER_HEX_FILLED; |
|
|
|
|
v2f uv_coords = (hxi.selected) ? hg.selected_fill_color_uv : hg.fill_color_uv; |
|
|
|
|
|
|
|
|
|
for (uint i = 0; i < IDX_PER_HEX_FILLED; i += 3) { |
|
|
|
|
// cheat at vertex normals since all hexes lay flat on z-axis
|
|
|
|
|
normal_buf.buffer[idx + i + 0] = 0.f; |
|
|
|
|
normal_buf.buffer[idx + i + 1] = 0.f; |
|
|
|
|
normal_buf.buffer[idx + i + 2] = 1.f; |
|
|
|
|
|
|
|
|
|
// fill uv_buffer with palette texture coords
|
|
|
|
|
uv_buf.buffer[idx + i + 0] = uv_coords.x; |
|
|
|
|
uv_buf.buffer[idx + i + 1] = uv_coords.y; |
|
|
|
|
uv_buf.buffer[idx + i + 2] = 0; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void |
|
|
|
|
insertHexVertexData(render_group* rg_filled, render_group* rg_lines, hex_info& hxi) |
|
|
|
|
{ |
|
|
|
|
gl_buffer& filled_vbuf = rg_filled->render_objects[0]->vertex_buffer; |
|
|
|
|
gl_buffer& lines_vbuf = rg_lines->render_objects[0]->vertex_buffer; |
|
|
|
|
uint filled_verts_per_hex = 54; |
|
|
|
|
uint line_verts_per_hex = 36; |
|
|
|
|
uint i_filled = hxi.hexID * filled_verts_per_hex; |
|
|
|
|
uint i_lines = hxi.hexID * line_verts_per_hex; |
|
|
|
|
|
|
|
|
|
assert(filled_vbuf.max_count >= i_filled + filled_verts_per_hex && |
|
|
|
|
lines_vbuf.max_count >= i_lines + line_verts_per_hex); |
|
|
|
|
|
|
|
|
|
// copy/pasted from scene_loader
|
|
|
|
|
// TODO: move scene_loader hex stuff to this file and refactor
|
|
|
|
|
GLfloat* fb = filled_vbuf.buffer; |
|
|
|
|
uint idx = i_filled; |
|
|
|
|
|
|
|
|
|
// triangles
|
|
|
|
|
for (uint j = 0; j < 6; j++) { |
|
|
|
|
for (uint i = idx, j = 0; j < 6; i += 9, j++) { |
|
|
|
|
// vertex 0
|
|
|
|
|
fb[idx + 0] = (GLfloat) hxi.XPos; |
|
|
|
|
fb[idx + 1] = (GLfloat) hxi.YPos; |
|
|
|
|
fb[idx + 2] = (GLfloat) 0.f; |
|
|
|
|
vbuf.buffer[i + 0] = (GLfloat) hxi.XPos; |
|
|
|
|
vbuf.buffer[i + 1] = (GLfloat) hxi.YPos; |
|
|
|
|
vbuf.buffer[i + 2] = (GLfloat) 0.f; |
|
|
|
|
|
|
|
|
|
// vertex 1
|
|
|
|
|
fb[idx + 3] = (GLfloat) hxi.vertices[j].x; |
|
|
|
|
fb[idx + 4] = (GLfloat) hxi.vertices[j].y; |
|
|
|
|
fb[idx + 5] = (GLfloat) 0.f; |
|
|
|
|
vbuf.buffer[i + 3] = (GLfloat) hxi.vertices[j].x; |
|
|
|
|
vbuf.buffer[i + 4] = (GLfloat) hxi.vertices[j].y; |
|
|
|
|
vbuf.buffer[i + 5] = (GLfloat) 0.f; |
|
|
|
|
|
|
|
|
|
if (j == 5) { // re-use the first point for the last triangle
|
|
|
|
|
// vertex 2
|
|
|
|
|
fb[idx + 6] = (GLfloat) hxi.vertices[0].x; |
|
|
|
|
fb[idx + 7] = (GLfloat) hxi.vertices[0].y; |
|
|
|
|
fb[idx + 8] = (GLfloat) 0.f; |
|
|
|
|
vbuf.buffer[i + 6] = (GLfloat) hxi.vertices[0].x; |
|
|
|
|
vbuf.buffer[i + 7] = (GLfloat) hxi.vertices[0].y; |
|
|
|
|
vbuf.buffer[i + 8] = (GLfloat) 0.f; |
|
|
|
|
} else { |
|
|
|
|
// vertex 2
|
|
|
|
|
fb[idx + 6] = (GLfloat) hxi.vertices[j + 1].x; |
|
|
|
|
fb[idx + 7] = (GLfloat) hxi.vertices[j + 1].y; |
|
|
|
|
fb[idx + 8] = (GLfloat) 0.f; |
|
|
|
|
vbuf.buffer[i + 6] = (GLfloat) hxi.vertices[j + 1].x; |
|
|
|
|
vbuf.buffer[i + 7] = (GLfloat) hxi.vertices[j + 1].y; |
|
|
|
|
vbuf.buffer[i + 8] = (GLfloat) 0.f; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
idx += 9; // NOTE: 3 vertices * 3 floats;
|
|
|
|
|
void |
|
|
|
|
populateLineGLBuffers(hexgrid& hg, hex_info& hxi, render_group* rg_lines) |
|
|
|
|
{ |
|
|
|
|
render_object* ro = rg_lines->render_objects[0]; |
|
|
|
|
gl_buffer& vbuf = ro->vertex_buffer; |
|
|
|
|
gl_buffer& normal_buf = ro->normal_buffer; |
|
|
|
|
gl_buffer& uv_buf = ro->uv_buffer; |
|
|
|
|
uint idx = hxi.hexID * IDX_PER_HEX_LINES; |
|
|
|
|
|
|
|
|
|
for (uint i = 0; i < IDX_PER_HEX_LINES; i += 3) { |
|
|
|
|
// cheat at vertex normals since all hexes lay flat on z-axis
|
|
|
|
|
normal_buf.buffer[idx + i + 0] = 0.f; |
|
|
|
|
normal_buf.buffer[idx + i + 1] = 0.f; |
|
|
|
|
normal_buf.buffer[idx + i + 2] = 1.f; |
|
|
|
|
|
|
|
|
|
// fill uv_buffer with palette texture coords
|
|
|
|
|
uv_buf.buffer[idx + i + 0] = hg.line_color_uv.x; |
|
|
|
|
uv_buf.buffer[idx + i + 1] = hg.line_color_uv.y; |
|
|
|
|
uv_buf.buffer[idx + i + 2] = 0; |
|
|
|
|
} |
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, filled_vbuf.buffer_id); |
|
|
|
|
// TODO: we don't actually have to upload the whole buffer w/ buffersubdata
|
|
|
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, filled_vbuf.count * sizeof(GLfloat), filled_vbuf.buffer); |
|
|
|
|
|
|
|
|
|
gl_buffer& normal_buf = rg_filled->render_objects[0]->normal_buffer; |
|
|
|
|
for (uint i = 0; i < filled_verts_per_hex; i+=3) { |
|
|
|
|
normal_buf.buffer[i_filled + i + 0] = 0.f; |
|
|
|
|
normal_buf.buffer[i_filled + i + 1] = 0.f; |
|
|
|
|
normal_buf.buffer[i_filled + i + 2] = 1.f; |
|
|
|
|
|
|
|
|
|
Point p1, p2; |
|
|
|
|
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]; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
vbuf.buffer[idx + 0] = p1.x; |
|
|
|
|
vbuf.buffer[idx + 1] = p1.y; |
|
|
|
|
vbuf.buffer[idx + 2] = 0.f; |
|
|
|
|
vbuf.buffer[idx + 3] = p2.x; |
|
|
|
|
vbuf.buffer[idx + 4] = p2.y; |
|
|
|
|
vbuf.buffer[idx + 5] = 0.f; |
|
|
|
|
idx += 6; |
|
|
|
|
} |
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, normal_buf.buffer_id); |
|
|
|
|
glBufferSubData(GL_ARRAY_BUFFER, 0, normal_buf.count * sizeof(GLfloat), normal_buf.buffer); |
|
|
|
|
} |
|
|
|
|
|