Browse Source

testing hash_map grid type

master
cinnaboot 8 years ago
parent
commit
882236cbf0
  1. 3
      TODO.md
  2. 62
      data/hashmap_scene.json
  3. 0
      data/hashmap_scene_hexmap.json
  4. 48
      data/level.2.dae
  5. 10
      data/scene_schema.json
  6. 11
      src/gooey.cpp
  7. 4
      src/hexgame.cpp
  8. 36
      src/hexgrid.cpp
  9. 5
      src/hexgrid.h
  10. 54
      src/scene_loader.cpp
  11. 3
      src/scene_loader.h
  12. 39
      src/util.cpp
  13. 9
      src/util.h

3
TODO.md

@ -1,8 +1,10 @@
## TODO:
- better (flat) level mesh for testing grid position
- reduce verbosity of assimp loading
- make hashmap grid type
- in-game editor for adding removing hexes to line up with terrain/indoor meshes
- need to update json schema with "oneOf" to validate different grid types
- position entities on grid hexes
- gooey
- add object inspector window
@ -24,6 +26,7 @@
- show debug mesh for light positions
- attenuate point lights in shader
- simplify render_object buffers into 2d array or vector, and use stride when pushing to GL
- render debug bounding boxes for meshes (including hexgrid)
- remove checks for colors, textures from render_group functions
- actually cannot remove checks for texture because some meshes aren't loaded properly
- maybe can cause loading mesh to fail when more than one mesh per file

62
data/hashmap_scene.json

@ -0,0 +1,62 @@
{
"camera" : {
"position" : {"x":400,"y":-275,"z":325},
"target" : {"x":140,"y":0,"z":0},
"world_up" : {"x":0,"y":0,"z":1}
},
"hex_grid" : {
"position" : {"x":0,"y":0,"z":0},
"hex_size" : 10,
"fill_color" : 6,
"selected_fill_color": 7,
"hex_line_color": 5,
"hexlib_orientation" : "layout_flat",
"grid_type" : "hash_map",
"map_file" : "hashmap_scene_hexmap.json"
},
"entities" : [
{
"name" : "catepillar 1",
"model_file" : "catepillar.dae",
"position" : {"x":-140,"y":50,"z":0},
"rotation" : {"x":0,"y":0,"z":0,"w":0},
"scale" : {"x":10,"y":10,"z":10}
},
{
"name" : "catepillar 2",
"model_file" : "catepillar.dae",
"position" : {"x" :140,"y":0,"z":0},
"rotation" : {"x":0,"y":0,"z":0,"w":0},
"scale" : {"x":10,"y":10,"z":10}
},
{
"name" : "box",
"model_file" : "block2.dae",
"position" : {"x":140,"y":-100,"z":0},
"rotation" : {"x":0,"y":0,"z":0,"w":0},
"scale" : {"x":10,"y":10,"z":10}
},
{
"name" : "ground",
"model_file" : "level.2.dae",
"position" : {"x":0,"y":0,"z":-1},
"rotation" : {"x":0,"y":0,"z":0,"w":0},
"scale" : {"x":300,"y":300,"z":300}
}
],
"lights" : [
{
"intensity" : 1.0,
"color" : {"r":0,"g":0,"b":0},
"position" : {"x":-1000,"y":0,"z":200}
},
{
"intensity" : 1.0,
"color" : {"r":0,"g":0,"b":0},
"position" : {"x":200,"y":0,"z":200}
}
]
}

0
data/hashmap_scene_hexmap.json

48
data/level.2.dae

File diff suppressed because one or more lines are too long

10
data/scene_schema.json

@ -55,8 +55,11 @@
"hex_line_color" : { "type": "number" },
"hexlib_orientation" : { "type": "string" },
"hex_size" : { "type": "number" },
"grid_type" : { "type": "string" },
"hex_radius" : { "type": "number" }
"grid_type" : { "enum": ["hexagon", "hash_map"] },
"oneOf": [
{"properties": {"hex_radius": { "type": "number" }}, "required": ["hex_radius"]},
{"properties": {"map_file": {"type": "string"}}, "required": ["map_file"]}
]
},
"required": [
"position",
@ -65,8 +68,7 @@
"hex_line_color",
"hexlib_orientation",
"hex_size",
"grid_type",
"hex_radius"
"grid_type"
]
},

11
src/gooey.cpp

@ -15,6 +15,7 @@
#include "hexgrid.h"
#include "util.h"
#include "gooey.h"
#include "scene_loader.h"
// forward declarations
@ -135,10 +136,18 @@ void
renderHexgridWindow(hexgrid& grid, ImGuiWindowFlags window_flags)
{
ImGui::SetNextWindowPos(ImVec2(0,270));
ImGui::SetNextWindowSize(ImVec2(350, 350));
ImGui::SetNextWindowSize(ImVec2(350, 370));
ImGui::SetNextWindowBgAlpha(0.3f);
ImGui::Begin("Hexgrid", nullptr, window_flags);
// NOTE: only show file dialog for hash_map grid type
if (grid.gridT == HASH_MAP) {
ImGui::Text(grid.map_file);
if (ImGui::Button("Save")) {
slSaveGridFile(grid);
}
}
ImGui::Text("Draw Mode:");
if (ImGui::RadioButton("None", (grid.draw_mode == NONE)))
grid.draw_mode = NONE;

4
src/hexgame.cpp

@ -7,7 +7,7 @@
#define VSYNC_ENABLED true
#define DATA_DIR "../data"
#define DEFAULT_SCENE_FILE "test_scene.json"
#define DEFAULT_SCENE_FILE "hashmap_scene.json"
#define SCENE_SCHEMA_FILE "scene_schema.json"
#define MAX_ENTITIES 1000
@ -62,7 +62,7 @@ loadSceneFromJson(game_state* s, render_state* rs)
slParseHexGrid(sd, gs->grid, rs->palette_image);
if (slCreateHexRenderGroups(gs->grid, rs)) {
if (!hgInit(gs->grid, rs->filled_hex_render_group, rs->hex_line_render_group)) {
if (!hgInit(gs->grid, rs->filled_hex_render_group, rs->hex_line_render_group, DATA_DIR)) {
slFreeSceneDoc(sd);
return false;
}

36
src/hexgrid.cpp

@ -7,6 +7,7 @@
// forward declarations
hex_info createHexInfo(hexgrid& hg, int q, int r);
void createHexagonGrid(hexgrid& hg);
bool createHashMapGrid(hexgrid& hg, const char* data_dir);
void populateFilledHexGLBuffers(hexgrid& hg, hex_info& hxi, render_group* rg_filled);
void populateLineGLBuffers(hexgrid& hg, hex_info& hxi, render_group* rg_lines);
@ -14,16 +15,22 @@ void populateLineGLBuffers(hexgrid& hg, hex_info& hxi, render_group* rg_lines);
// interface
bool
hgInit(hexgrid& hg, render_group* rg_filled, render_group* rg_lines)
hgInit(hexgrid& hg, render_group* rg_filled, render_group* rg_lines, const char* data_dir)
{
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 {
LOG(ERROR) << "Unhandled grid type\n";
return false;
switch (hg.gridT) {
case HEXAGON:
createHexagonGrid(hg);
break;
case HASH_MAP:
if (!createHashMapGrid(hg, data_dir))
return false;
break;
default:
LOG(ERROR) << "Unhandled grid type\n";
return false;
}
uint hex_count = hg.hex_map.size();
@ -338,6 +345,23 @@ createHexagonGrid(hexgrid& hg)
}
}
bool
createHashMapGrid(hexgrid& hg, const char* data_dir)
{
LOG(DEBUG) << "starting createHashMapGrid with map_file: " << hg.map_file << "\n";
uint max_len = 256;
char full_path[max_len];
if (utilConcatPath(full_path, data_dir, hg.map_file, max_len)) {
char* hashmap_contents = utilDumpTextFile(full_path);
// parse contents
// insert hexes into hex_map
return true;
}
return false;
}
void
populateFilledHexGLBuffers(hexgrid& hg, hex_info& hxi, render_group* rg_filled)
{

5
src/hexgrid.h

@ -69,6 +69,9 @@ struct hexgrid
v3f position;
v3f normal;
uint hex_size;
// NOTE: all these properties aren't used by every map type
char map_file[256];
uint hex_radius;
v2f fill_color_uv;
@ -84,7 +87,7 @@ struct hexgrid
};
bool hgInit(hexgrid& hg, render_group* rg_filled, render_group* rg_lines);
bool hgInit(hexgrid& hg, render_group* rg_filled, render_group* rg_lines, const char* data_dir);
bool hgAddHex(hexgrid& hg, v3f hex_coords, render_group* rg_filled, render_group* rg_lines);

54
src/scene_loader.cpp

@ -6,6 +6,7 @@
#include <rapidjson/schema.h>
#include <rapidjson/stringbuffer.h>
#include <rapidjson/error/en.h>
#include <rapidjson/writer.h>
#include "aixlog.hpp"
#include "entity.h"
@ -19,6 +20,10 @@ struct slSceneDoc
rapidjson::Document* doc;
};
// TODO: find a better way to avoid threading 'data_dir' through gooey
// this would be a good candidate to go in some global application config structure
static const char* g_data_dir;
// forward declarations
bool parseFile(rapidjson::Document* doc, const char* data_dir, const char* file_name);
@ -46,6 +51,7 @@ slLoadFile(const char* data_dir, const char* scene_file, const char* schema_file
return nullptr;
}
g_data_dir = data_dir;
return sd;
}
@ -114,20 +120,26 @@ slParseHexGrid(slSceneDoc* sd, hexgrid& hg, util_image& palette_image)
const rapidjson::Value& json_grid = (*sd->doc)["hex_grid"];
std::string grid_type_str = json_grid["grid_type"].GetString();
if (grid_type_str == "hexagon")
if (grid_type_str == "hexagon") {
hg.gridT = HEXAGON;
hg.hex_radius = json_grid["hex_radius"].GetInt();
}
else if (grid_type_str == "parallelogram")
hg.gridT = PARALLELOGRAM;
else if (grid_type_str == "rhombus")
hg.gridT = RHOMBUS;
else if (grid_type_str == "hash_map")
else if (grid_type_str == "hash_map") {
hg.gridT = HASH_MAP;
// NOTE: 256 is the size of hg.map_file[256]
// TODO: should probably define max_len as a constant somewhere
utilCopyCStr(hg.map_file, utilBaseName(json_grid["map_file"].GetString()), 256);
}
hg.hex_size = json_grid["hex_size"].GetInt();
glm::vec3 pos = parseVec3(json_grid["position"]);
hg.position.x = pos.x;
hg.position.y = pos.y;
hg.position.z = pos.z;
hg.hex_size = json_grid["hex_size"].GetInt();
hg.fill_color_uv = utilGetPaletteCoords(palette_image, json_grid["fill_color"].GetInt());
hg.selected_fill_color_uv = utilGetPaletteCoords(palette_image,
@ -136,10 +148,6 @@ slParseHexGrid(slSceneDoc* sd, hexgrid& hg, util_image& palette_image)
std::string orientation_str = json_grid["hexlib_orientation"].GetString();
hg.layout_mode = (orientation_str == "layout_flat") ? LAYOUT_FLAT : LAYOUT_POINTY;
if (hg.gridT == HEXAGON) {
hg.hex_radius = json_grid["hex_radius"].GetInt();
}
}
bool
@ -182,6 +190,38 @@ slParseLights(slSceneDoc* sd, rg_point_light* lights, uint& num_lights, uint max
return true;
}
bool
slSaveGridFile(hexgrid& hg)
{
uint max_len = 256;
char full_path[max_len];
if (utilConcatPath(full_path, g_data_dir, hg.map_file, max_len)) {
LOG(INFO) << "saving grid file: " << full_path << "\n";
// assemble json from hexgrid
rapidjson::Document doc;
// need to store grid properties: hex_size, world origin, world normal?, layout_mode?
// hex properties: hex space coordinates, world XPos/YPos, world hex vertices
// write document to buffer
rapidjson::StringBuffer sb;
rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
doc.Accept(writer);
// write buffer to file
if (utilWriteTextFile(full_path, sb.GetString())) {
LOG(INFO) << "save successful\n";
return true;
}
LOG(ERROR) << "error saving file: " << full_path << "\n";
return false;
}
LOG(ERROR) << "error creating path\n";
return false;
}
// internal

3
src/scene_loader.h

@ -30,3 +30,6 @@ void slParseHexGrid(slSceneDoc* sd, hexgrid& hg, util_image& palette_image);
bool slCreateHexRenderGroups(hexgrid& hg, render_state* rs);
bool slParseLights(slSceneDoc* sd, rg_point_light* lights, uint& num_lights, uint max_lights);
// TODO: this is pretty hacky atm just for testing
bool slSaveGridFile(hexgrid& hg);

39
src/util.cpp

@ -30,6 +30,35 @@ utilBaseName(const char* path_str)
return path_str;
}
bool
utilCopyCStr(char* dest, const char* src, uint max_len)
{
assert(std::strlen(src) < MAX_STRING_LENGTH && max_len <= MAX_STRING_LENGTH);
if (std::strlen(src) + 1 > max_len)
return false;
std::memcpy(dest, src, std::strlen(src) + 1);
return true;
}
bool
utilConcatPath(char* out, const char* base_dir, const char* file_name, uint max_len)
{
size_t l1 = std::strlen(base_dir);
size_t l2 = std::strlen(file_name);
size_t padded = l1 + l2 + 2; // NOTE: null term + '/'
if (padded <= MAX_STRING_LENGTH && padded <= max_len) {
int c = std::snprintf(out, padded, "%s/%s", base_dir, file_name);
if (c > 0)
return true;
else
return false;
}
return false;
}
// TODO: don't use ftell() to get filesize
// https://wiki.sei.cmu.edu/confluence/display/c/FIO19-C.+Do+not+use+fseek%28%29+and+ftell%28%29+to+compute+the+size+of+a+regular+file
char *
@ -54,6 +83,13 @@ utilDumpTextFile(const char* filename)
return buf;
}
bool
utilWriteTextFile(const char* filename, const char* text)
{
return false;
}
void *
utilLogAlloc(uint item_count, uint type_size, const char* file_name, const int line)
{
@ -85,7 +121,8 @@ utilLoadImage(const char* base_dir, const char* filename)
{
const uint max_path = 256; // NOTE: util_image.file_path is char[256]
const char* base_name = utilBaseName(filename);
uint l = std::strlen(base_dir) + std::strlen(base_name) + 1; // NOTE: +1 for '/' char
// NOTE: +1 for '/' char, +1 for null
uint l = std::strlen(base_dir) + std::strlen(base_name) + 2;
assert(l < max_path);
char full_path[l];
std::memcpy(full_path, base_dir, std::strlen(base_dir) + 1);

9
src/util.h

@ -101,6 +101,13 @@ utilConvertColor(GLfloat buf[3], uint32 color)
buf[2] = (GLfloat) ((color >> 8) & 0xFF) / (GLfloat) 255;
}
// NOTE: max_len should be the allocated size of dest
bool utilCopyCStr(char* dest, const char* src, uint max_len);
// NOTE: returns new string with '/' between
// NOTE: max_len should be the size of return buffer.
bool utilConcatPath(char* out, const char* base_dir, const char* file_name, uint max_len);
const char* utilBaseName(const char* path_str);
// NOTE: Wrapper for calloc that will send error message on out of memory
@ -111,6 +118,8 @@ void utilSafeFree(const void* mem);
char* utilDumpTextFile(const char* filename);
bool utilWriteTextFile(const char* filename, const char* text);
util_image utilLoadImage(const char* base_dir, const char* filename);
void utilFreeImage(util_image image);

Loading…
Cancel
Save