diff --git a/src/gooey.h b/src/gooey.h index c39918b..65ed221 100644 --- a/src/gooey.h +++ b/src/gooey.h @@ -59,7 +59,7 @@ renderGooey(SDL_Handles &handles, HexDrawMode &mode, bool &is_debug, window_flags |= ImGuiWindowFlags_NoCollapse; ImGui::SetNextWindowPos(ImVec2(0,0)); - ImGui::SetNextWindowSize(ImVec2(300, 550)); + ImGui::SetNextWindowSize(ImVec2(300, 720)); ImGui::SetNextWindowBgAlpha(0.3f); bool show_window; ImGui::Begin("", &show_window, window_flags); diff --git a/src/hexgame.cpp b/src/hexgame.cpp index 26ba44e..0243de0 100644 --- a/src/hexgame.cpp +++ b/src/hexgame.cpp @@ -175,23 +175,49 @@ updateHexConeFill(int32 x, int32 y) if (hxi && (hxi != g_game_state->current_hex) && g_game_state->start_hex) { g_game_state->current_hex = hxi; + vector hexes = hex_conefill(g_game_state->start_hex->hex, hxi->hex); - for (hex_info &h : *g_game_state->hex_array) + // TODO: Remove debug code here and from gooey.h + Point p1(g_game_state->start_hex->XPos, g_game_state->start_hex->YPos); + Point p2(g_game_state->current_hex->XPos, g_game_state->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 = 30.f * M_PI / 180; // M_PI is non-standard and may not be portable + + real64 x1 = len * std::cos(angle); + real64 y1 = len * std::sin(angle); + // top of cone + real64 topX = x1 * std::cos(coneAngle) - y1 * std::sin(coneAngle) + p1.x; + real64 topY = x1 * std::sin(coneAngle) + y1 * std::cos(coneAngle) + p1.y; + // bottom of cone + real64 botX = x1 * std::cos(coneAngle) + y1 * std::sin(coneAngle) + p1.x; + real64 botY = x1 * std::sin(-1 * coneAngle) + y1 * std::cos(coneAngle) + p1.y; + + hex_info* topHex = getSingleHex(topX, topY); + hex_info* botHex = getSingleHex(botX, botY); + + if (topHex && botHex) { - // TODO: define a system of linear inequalities in hex-space to represent - // cones/arbitrary polygons - if (&h == g_game_state->start_hex) - continue; + Point test_p; + Point vert2 = Point(botHex->XPos, botHex->YPos); + Point vert4 = Point(topHex->XPos, topHex->YPos); + std::vector vertices = {p1, vert2, p2, vert4}; - if (hex_equal(h.hex, hxi->hex)) - { - h.selected = true; - h.current_color = g_render_state->selected_fill_color; - } - else + for (hex_info &h : *g_game_state->hex_array) { - h.selected = false; - h.current_color = h.stored_color; + test_p.x = h.XPos; + test_p.y = h.YPos; + + if (crossingTest(vertices, test_p)) + { + h.selected = true; + h.current_color = g_render_state->selected_fill_color; + } + else + { + h.selected = false; + h.current_color = h.stored_color; + } } } } @@ -385,7 +411,7 @@ int main(int argc, char* argv[]) g_game_state->is_selecting = false; g_game_state->start_hex = 0x0; g_game_state->current_hex = 0x0; - g_game_state->draw_mode = LINE; + g_game_state->draw_mode = CONE_FILL; // init global render state g_render_state = new render_state(); diff --git a/src/hexlib.h b/src/hexlib.h index 69b08c5..30d0beb 100644 --- a/src/hexlib.h +++ b/src/hexlib.h @@ -263,9 +263,77 @@ vector polygon_corners(Layout layout, Hex h) // custom hex functions -bool hex_equal(Hex a, Hex b) +bool +hex_equal(Hex a, Hex b) { return (a.q == b.q && a.r == b.r && a.s == b.s); } +vector +hex_conefill(Hex a, Hex b) +{ + vector results = {}; + + return results; +} + +// NOTE: implementation of this line crossing test +// https://graphics.stanford.edu/pub/Graphics/RTNews/html/rtnv5n3.html#art3 +// NOTE: assumes use of convex polygons with vertices in CCW layout +bool +crossingTest(vector vertices, Point p) +{ + int numVertices = vertices.size(), intersect_count = 0; + Point vert0, vert1; + double m, x; + + if (numVertices < 3) + return false; + + vert0 = vertices[0]; + + for (int i = 1; i < numVertices + 1; i++) + { + // use first vertex for the last edge + if (i == numVertices) + vert1 = vertices[0]; + else + vert1 = vertices[i]; + + // check if edge can intersect the +X ray + if ((vert0.y >= p.y && vert1.y <= p.y) || + (vert0.y <= p.y && vert1.y >= p.y)) + { + // TODO: these checks for undefined is pretty hacky + double dx = vert1.x - vert0.x; + // solve for point on edge where y = p.y + if (dx == 0) // don't divide by zero + x = (vert0.x == 0) ? 1 : vert0.x; + else + { + double dm = vert1.x - vert0.x; + if (dm == 0) // don't divide by 0 + x = (vert0.x == 0) ? 1 : vert0.x; + else + { + m = (vert1.y - vert0.y) / (dm); + x = (p.y - vert0.y) / m + vert0.x; + } + } + // if x is right of p.x it must intersect + if (x >= p.x) + intersect_count++; + + // 2 intersections of convex polygon means we started outside + if (intersect_count > 1) + return false; + } + + // start with previous vertex on next loop + vert0 = vert1; + } + + return (intersect_count == 1); +} + #endif // HEXLIB_H diff --git a/src/renderer.h b/src/renderer.h index ef3cbfa..ed36d07 100644 --- a/src/renderer.h +++ b/src/renderer.h @@ -97,6 +97,7 @@ gl_render_group g_debug_render_group; // Interface bool initRenderer(SDL_Handles &handles, v2i vpDims); +bool addTexture(SDL_Handles &handles, std::string path); bool createScene(std::vector* hexes); void renderFrame(const std::vector *hexes); void renderDebug(hex_info *start_hex, hex_info * current_hex);