Browse Source

update hexgrid and functions to store hexes in hashtable

master
cinnaboot 8 years ago
parent
commit
d7eb8ae28d
  1. 2
      TODO.md
  2. 4
      data/level.2.dae
  3. 1
      src/gooey.cpp
  4. 7
      src/hexgame.cpp
  5. 82
      src/hexgrid.cpp
  6. 40
      src/hexgrid.h
  7. 4
      src/hexlib.h
  8. 41
      src/scene_loader.cpp

2
TODO.md

@ -42,7 +42,9 @@
- move from COLLADA output to glTF (GL Transmission Format) https://www.khronos.org/gltf/
- add config.js/yaml for application config (remove some defines everywhere)
- maybe try deferred rendering at some point to use a ton of lights
- use assimp material info in shaders for fancier lighting
- add cpu performance counters in render loop
- hgUpdateUV buffer can probably be improved by adding selected hexes to a small cache structure
- check for memory leaks w/ valgrind
## DONE:

4
data/level.2.dae

@ -12,7 +12,7 @@
</asset>
<library_images>
<image id="palette_png" name="palette_png">
<init_from>/home/doug/dev/blender.projects/palette.png</init_from>
<init_from>palette.png</init_from>
</image>
</library_images>
<library_effects>
@ -109,4 +109,4 @@
<scene>
<instance_visual_scene url="#Scene"/>
</scene>
</COLLADA>
</COLLADA>

1
src/gooey.cpp

@ -151,6 +151,7 @@ renderHexgridWindow(hexgrid& grid, ImGuiWindowFlags window_flags)
ImGui::Separator();
ImGui::Text("is_selecting");
ImGui::SameLine(); ImGui::TextUnformatted(grid.is_selecting ? "true" : "false");
ImGui::Text("Hex Count: %lu", grid.hex_map.size());
ImGui::Text("current_hex: ");
if (grid.current_hex) {

7
src/hexgame.cpp

@ -86,8 +86,10 @@ init()
{
// init global game state
g_game_state = UTIL_ALLOC(1, game_state);
g_game_state->grid.hex_array = new vector<hex_info>;
g_game_state->entities = UTIL_ALLOC(MAX_ENTITIES, Entity);
// TODO: I think this is necessary because we're using calloc to initialize gamestate
// which contains the hashtable.
g_game_state->grid.hex_map = std::unordered_map<Hex, hex_info, hex_hashfunc>();
// init global render state
g_render_state = UTIL_ALLOC(1, render_state);
@ -330,9 +332,6 @@ cleanUp(SDL_Handles &handles)
game_state* gs = g_game_state;
if (g_game_state->grid.hex_array)
delete g_game_state->grid.hex_array;
for (uint i = 0; i < gs->entity_count; i++) {
meFreeMeshGroup(gs->entities[i].mesh_group);
rgFree(gs->entities[i].ren_group);

82
src/hexgrid.cpp

@ -5,7 +5,7 @@
// forward declarations
bool createHexagonGrid(hexgrid hg);
bool createHexagonGrid(hexgrid& hg);
// interface
@ -29,10 +29,10 @@ hgGetSingleHex(hexgrid& hg, real32 x, real32 y)
Point p(x, y);
Hex h = hex_round(pixel_to_hex(hg.hexlib_layout, p));
for (hex_info &hxi : *hg.hex_array) {
if (hex_equal(h, hxi.hex))
return &hxi;
}
auto it = hg.hex_map.find(h);
if (it != hg.hex_map.end())
return &it->second;
return nullptr;
}
@ -40,11 +40,10 @@ hgGetSingleHex(hexgrid& hg, real32 x, real32 y)
void
hgResetHexes(hexgrid& hg)
{
hg.start_hex = hg.current_hex = 0;
hg.start_hex = hg.current_hex = nullptr;
for (hex_info &hxi : *hg.hex_array) {
hxi.selected = false;
}
for (auto& it : hg.hex_map)
it.second.selected = false;
}
void
@ -56,12 +55,11 @@ hgUpdateHexFill(hexgrid& hg, int32 x, int32 y)
hg.current_hex = hxi;
int l = hex_distance(hg.start_hex->hex, hg.current_hex->hex);
for (hex_info &h : *hg.hex_array)
{
if (hex_distance(hg.start_hex->hex, h.hex) <= l)
h.selected = true;
for (auto& it: hg.hex_map) {
if (hex_distance(hg.start_hex->hex, it.second.hex) <= l)
it.second.selected = true;
else
h.selected = false;
it.second.selected = false;
}
}
}
@ -72,24 +70,18 @@ hgUpdateHexLineDraw(hexgrid& hg, int32 x, int32 y)
hex_info *hxi = hgGetSingleHex(hg, x, y);
if (hxi && (hxi != hg.current_hex) && hg.start_hex)
{
// TODO: can avoid this loop by caching selected hexes
for (auto& it : hg.hex_map)
it.second.selected = false;
hg.current_hex = hxi;
vector<Hex> hexLine = hex_linedraw(hg.start_hex->hex, hxi->hex);
for (hex_info &h1 : *hg.hex_array)
{
for (uint i = 0; i < hexLine.size(); i++)
{
Hex h2 = hexLine[i];
if (hex_equal(h1.hex, h2))
{
h1.selected = true;
break;
}
else if (i == hexLine.size() - 1)
{
h1.selected = false;
}
}
for (Hex h : hexLine) {
auto it = hg.hex_map.find(h);
if (it != hg.hex_map.end())
it->second.selected = true;
}
}
}
@ -123,8 +115,9 @@ hgUpdateHexConeFill(hexgrid& hg, int32 x, int32 y, float cone_angle, std::vector
Point vert4 = Point(topX, topY);
std::vector<Point> vertices = {p1, vert2, p2, vert4};
for (hex_info &h : *hg.hex_array)
{
for (auto& it : hg.hex_map) {
hex_info& h = it.second;
test_p.x = h.XPos;
test_p.y = h.YPos;
@ -146,12 +139,13 @@ 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_array->size() * buf_len_per_hex);
for (uint i = 0; i < hg.hex_array->size(); i++) {
hex_info hxi = (*hg.hex_array)[i];
assert(buf_len == hg.hex_map.size() * buf_len_per_hex);
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 = i * buf_len_per_hex;
uint buf_idx = hxi.hexID * buf_len_per_hex;
for (uint j = 0; j < buf_len_per_hex; j +=3) {
uv_buffer[buf_idx + j + 0] = uv_coords.x;
@ -164,25 +158,19 @@ hgUpdateUVBuffer(hexgrid& hg, float* uv_buffer, uint buf_len)
// internal
bool
createHexagonGrid(hexgrid hg)
createHexagonGrid(hexgrid& hg)
{
if (hg.hex_array == nullptr) {
LOG(ERROR) << "hg.hex_array is not initialized\n";
return false;
}
int hr = hg.hex_radius;
int nhr = hg.hex_radius * -1;
for (int q = nhr; q <= hr; q++)
{
for (int q = nhr; q <= hr; q++) {
int r1 = std::max(nhr, -q - hr);
int r2 = std::min(hr, -q + hr);
for (int r = r1; r <= r2; r++)
{
for (int r = r1; r <= r2; r++) {
hex_info hxi;
hxi.hexID = (int32) hg.hex_array->size();
hxi.hexID = (int32) hg.hex_map.size();
hxi.selected = false;
hxi.hex.q = q; hxi.hex.r = r; hxi.hex.s = -q-r;
Point p = hex_to_pixel(hg.hexlib_layout, hxi.hex);
hxi.XPos = p.x;
@ -194,7 +182,7 @@ createHexagonGrid(hexgrid hg)
if ((q > -2 && q < 2) && (r > -2 && r < 2)) {
// skip
} else {
hg.hex_array->push_back(hxi);
hg.hex_map.insert({hxi.hex, hxi});
}
/////////////
}

40
src/hexgrid.h

@ -2,6 +2,7 @@
#pragma once
#include <vector>
#include <unordered_map>
#include "hexlib.h"
#include "render_group.h"
@ -29,33 +30,44 @@ enum grid_type
struct hex_info
{
int32 hexID = 0;
uint hexID;
Hex hex = {};
real64 XPos = 0;
real64 YPos = 0;
bool selected = false;
real64 XPos;
real64 YPos;
bool selected;
std::vector<Point> vertices;
};
struct hex_hashfunc
{
// NOTE: hash_combine from boost
size_t operator()(const Hex& h) const {
std::hash<int> int_hash;
size_t hq = int_hash(h.q);
size_t hr = int_hash(h.r);
return hq ^ (hr + 0x9e3779b9 + (hq << 6) + (hq >> 2));
}
};
struct hexgrid
{
grid_type gridT = HEXAGON;
grid_type gridT;
Layout hexlib_layout;
Orientation hexlib_orientation;
v3f position = v3f(0, 0, 0);
uint hex_size = 10;
uint hex_radius = 0;
v3f position;
uint hex_size;
uint hex_radius;
v2f fill_color_uv;
v2f selected_fill_color_uv;
v2f line_color_uv;
std::vector<hex_info>* hex_array = nullptr;
hex_info* start_hex = nullptr;
hex_info* current_hex = nullptr;
vector<hex_info> selected_hexes;
HexDrawMode draw_mode = CONE_FILL;
bool is_selecting = false;
std::unordered_map<Hex, hex_info, hex_hashfunc> hex_map;
hex_info* start_hex;
hex_info* current_hex;
HexDrawMode draw_mode;
bool is_selecting;
};
bool hgCreateHexes(hexgrid& hg);

4
src/hexlib.h

@ -32,6 +32,10 @@ struct Hex
int s;
Hex(int q_, int r_, int s_): q(q_), r(r_), s(s_) {}
Hex(): q(0), r(0), s(0) {}
bool operator==(const Hex& h) const {
return (h.q == q && h.r == r && h.s == s);
}
};
struct Orientation

41
src/scene_loader.cpp

@ -151,11 +151,11 @@ bool
slCreateHexRenderGroups(hexgrid& hg, render_state* rs)
{
// NOTE: 6 triangles * 3 vertices per triangle * 3 floats per vertex
uint buf_len = hg.hex_array->size() * 6 * 3 * 3;
uint buf_len = hg.hex_map.size() * 6 * 3 * 3;
rs->filled_hex_render_group = rgInitSingle(rs->default_shader, buf_len, true);
// NOTE: 6 lines * 2 vertices per line * 3 floats per vertex
buf_len = hg.hex_array->size() * 6 * 2 * 3;
buf_len = hg.hex_map.size() * 6 * 2 * 3;
rs->hex_line_render_group = rgInitSingle(rs->default_shader, buf_len, true, 0, GL_LINES);
render_group* rg_filled = rs->filled_hex_render_group;
@ -282,6 +282,8 @@ parseVec4(const rapidjson::Value& node)
return v4;
}
// TODO: these should probably move to hexgrid.cpp, and pass in each raw buffer
// to avoid render_group dependancy
void
populateFilledHexGLBuffers(hexgrid& hg, render_group* rg_filled)
{
@ -290,7 +292,7 @@ populateFilledHexGLBuffers(hexgrid& hg, render_group* rg_filled)
gl_buffer& normal_buf = ro->normal_buffer;
gl_buffer& uv_buf = ro->uv_buffer;
assert((hg.hex_array->size() * 6 * 3 * 3) == vbuf.buffer_len);
assert((hg.hex_map.size() * 6 * 3 * 3) == vbuf.buffer_len);
// fill uv_buffer with palette texture coords
hgUpdateUVBuffer(hg, uv_buf.buffer, uv_buf.buffer_len);
@ -304,10 +306,10 @@ populateFilledHexGLBuffers(hexgrid& hg, render_group* rg_filled)
GLfloat* buf = vbuf.buffer;
for (uint i = 0; i < hg.hex_array->size(); i++) {
for (auto& it : hg.hex_map) {
hex_info hex = (*hg.hex_array)[i];
uint idx = i * 54; // NOTE: 6 triangles * 3 vertices * 3 floats
hex_info hex = it.second;
uint idx = hex.hexID * 54; // NOTE: 6 triangles * 3 vertices * 3 floats
// triangles
for (uint j = 0; j < 6; j++) {
@ -322,15 +324,12 @@ populateFilledHexGLBuffers(hexgrid& hg, render_group* rg_filled)
buf[idx + 4] = (GLfloat) hex.vertices[j].y;
buf[idx + 5] = (GLfloat) 0.f;
if (j == 5) // re-use the first point for the last triangle
{
if (j == 5) { // re-use the first point for the last triangle
// vertex 2
buf[idx + 6] = (GLfloat) hex.vertices[0].x;
buf[idx + 7] = (GLfloat) hex.vertices[0].y;
buf[idx + 8] = (GLfloat) 0.f;
}
else
{
} else {
// vertex 2
buf[idx + 6] = (GLfloat) hex.vertices[j + 1].x;
buf[idx + 7] = (GLfloat) hex.vertices[j + 1].y;
@ -350,7 +349,7 @@ populateLineGLBuffers(hexgrid& hg, render_group* rg_lines)
gl_buffer& normal_buf = ro->normal_buffer;
gl_buffer& uv_buf = ro->uv_buffer;
assert((hg.hex_array->size() * 6 * 2 * 3) == vbuf.buffer_len);
assert((hg.hex_map.size() * 6 * 2 * 3) == vbuf.buffer_len);
// cheat at vertex normals since all hexes lay flat on z-axis
for (uint i = 0; i < normal_buf.buffer_len; i += 3) {
@ -367,19 +366,17 @@ populateLineGLBuffers(hexgrid& hg, render_group* rg_lines)
}
Point p1, p2;
// NOTE: these buffers won't be correctly indexed with hashtable, but that doesn't really
// matter for the lines, since they don't change color
int idx = 0;
for (int i = 0; i < (int) hg.hex_array->size(); i++)
{
hex_info hxi = (*hg.hex_array)[i];
for (int j = 0; j < 6; j ++)
{
if (j == 5) // wrap
{
for (auto it : hg.hex_map) {
hex_info hxi = it.second;
for (int j = 0; j < 6; j ++) {
if (j == 5) { // wrap
p1 = hxi.vertices[j];
p2 = hxi.vertices[0];
}
else
{
} else {
p1 = hxi.vertices[j];
p2 = hxi.vertices[j + 1];
}

Loading…
Cancel
Save