From 4e0cae59cac94182d8e32d2ca16de296a578a728 Mon Sep 17 00:00:00 2001 From: Noah Metz Date: Fri, 22 Nov 2024 19:36:14 -0700 Subject: [PATCH] Added function to convert hex world coordinate -> region hex coordinate + region hex index --- client/include/hex.h | 17 ++++- client/shader/hex.vert | 28 +------- client/src/editor.c | 43 ++++++------ client/src/hex.c | 150 ++++++++++++++++++++++++++++++++++++++++- 4 files changed, 188 insertions(+), 50 deletions(-) diff --git a/client/include/hex.h b/client/include/hex.h index 51af25b..c83d052 100644 --- a/client/include/hex.h +++ b/client/include/hex.h @@ -16,11 +16,16 @@ #define max(a, b) ((a > b) ? a : b) #define min(a, b) ((a < b) ? a : b) +typedef struct HexCoordStruct { + int32_t q; + int32_t r; +} HexCoord; + extern vec3 hex_vertices[]; extern vec3 hex_starts[]; extern vec3 hex_directions[]; -extern int32_t hex_starts_qr[][2]; -extern int32_t hex_directions_qr[][2]; +extern HexCoord hex_starts_qr[]; +extern HexCoord hex_directions_qr[]; extern int hex_indices[]; typedef struct GPUHexStruct { @@ -131,4 +136,12 @@ VkResult update_hex_click( HexContext* hex, RenderContext* gpu); +void hex_qr(uint32_t hex, HexCoord* world); + +void region_qr(HexCoord region, HexCoord* world); + +void hex_add(HexCoord from, HexCoord* to); + +void hex_index(HexCoord world, HexCoord* region, uint32_t* hex); + #endif diff --git a/client/shader/hex.vert b/client/shader/hex.vert index 4f7f0ed..740594a 100644 --- a/client/shader/hex.vert +++ b/client/shader/hex.vert @@ -53,33 +53,7 @@ void main() { } else { position.y = region.hexes[hex_index].heights[indices[gl_VertexIndex]-1] + region.y; } - color = int2color(region.hexes[hex_index].colors[indices[gl_VertexIndex]]); - - /* - vec2 hex_qr = start_coords[side]*radius + direction_coords[side]*(ring-(radius*side)); - vec2 world_qr = vec2(0, 0); - world_qr.x = hex_qr.x - + region_qr.x*((region_size-1)*2 + 1.0) - + region_qr.y*((region_size-1) + 0.0); - - world_qr.y = hex_qr.y - - region_qr.x*((region_size-1) + 0.5) - - region_qr.y*((region_size-1)*2 + 1.0); - - color = vec4(world_qr/100, 0, 1); - - vec4 hex_pos = vec4(0, 0, 0, 1); - hex_pos.x = x*hex_qr.x; - hex_pos.z = -z*hex_qr.y - z*hex_qr.x/2; - - vec4 world_pos = vec4(0, 0, 0, 1); - world_pos.x = hex_pos.x + region_pos.x; - world_pos.z = hex_pos.z + region_pos.z; - - vec2 world_qr = vec2(0, 0); - world_qr.x = world_pos.x/x; - world_qr.y = -world_pos.z/z - world_pos.x/(2*x); - */ + color = int2color(region.hexes[hex_index].colors[indices[gl_VertexIndex]]); gl_Position = pc.context.proj * pc.context.view * position; } diff --git a/client/src/editor.c b/client/src/editor.c index 080c871..8b8070e 100644 --- a/client/src/editor.c +++ b/client/src/editor.c @@ -943,33 +943,22 @@ VkResult update_hex_info_ui(ClientContext* context) { context->hex.data.clicked_hex); VK_RESULT(update_ui_string(temp, 0x02, 0, 0, &context->ui, &context->render)); - int32_t hex_index = context->hex.data.clicked_hex; - - float radius = 0; - float ring = 0; - int side = 0; - if(hex_index != 0) { - radius = floor(0.5 + sqrt(12*hex_index-3)/6); - ring = hex_index - (3*radius*radius - 3*radius + 1); - side = floor(ring/radius); - } - // TODO: fix, these are wrong lmao - int32_t hex_q = hex_starts_qr[side][0]*radius + hex_directions_qr[side][0]*(ring-(radius*side)); - int32_t hex_r = hex_starts_qr[side][1]*radius + hex_directions_qr[side][1]*(ring-(radius*side)); + HexCoord hex_world; + hex_qr(context->hex.data.clicked_hex, &hex_world); - int32_t region_q = region->data.q*((REGION_SIZE-1)*2 + 1) + region->data.r*(REGION_SIZE-1); - int32_t region_r = region->data.q*((REGION_SIZE-1) + 0.5) + region->data.r*((REGION_SIZE-1)*2+1); + HexCoord region_coord = {region->data.q, region->data.r}; + HexCoord region_world; + region_qr(region_coord, ®ion_world); - int32_t world_q = hex_q + region_q; - int32_t world_r = hex_r - region_r; + hex_add(region_world, &hex_world); snprintf( temp, sizeof(temp), "%d, %d, %d, %d", - world_q, - world_r, + hex_world.q, + hex_world.r, region->data.y, context->hex.data.clicked_vertex); VK_RESULT(update_ui_string(temp, 0x02, 0, 1, &context->ui, &context->render)); @@ -1205,6 +1194,22 @@ void editor_startup(ClientContext* context) { color_ui(context); } +void hex_vertex_neighbors( + uint32_t vertex, HexCoord region, uint32_t hex, + uint32_t n_vertex[2], HexCoord n_region[2], uint32_t n_hex[2]) { + HexCoord n1 = hex_directions_qr[(vertex+1) % 6]; + HexCoord n2 = hex_directions_qr[(vertex+2) % 6]; + + HexCoord hex_world; + HexCoord region_world; + + region_qr(region, ®ion_world); + hex_qr(hex, &hex_world); + hex_add(region_world, &hex_world); + hex_add(hex_world, &n1); + hex_add(hex_world, &n2); +} + int main() { EditorData* data = malloc(sizeof(EditorData)); memset(data, 0, sizeof(EditorData)); diff --git a/client/src/hex.c b/client/src/hex.c index 55069dc..c05ccd2 100644 --- a/client/src/hex.c +++ b/client/src/hex.c @@ -23,7 +23,7 @@ vec3 hex_starts[] = { { HEX_X, 0, HEX_Z/2}, }; -int32_t hex_starts_qr[][2] = { +HexCoord hex_starts_qr[] = { { 0, -1}, {-1, 0}, {-1, 1}, @@ -32,7 +32,7 @@ int32_t hex_starts_qr[][2] = { { 1, -1}, }; -int32_t hex_directions_qr[][2] = { +HexCoord hex_directions_qr[] = { {-1, 1}, { 0, 1}, { 1, 0}, @@ -1131,3 +1131,149 @@ VkResult update_hex_click( return VK_SUCCESS; } + +void hex_qr(uint32_t hex, HexCoord* world) { + float radius = 0; + float ring = 0; + int side = 0; + if(hex != 0) { + radius = floor(0.5 + sqrt(12*hex-3)/6); + ring = hex - (3*radius*radius - 3*radius + 1); + side = floor(ring/radius); + } + + world->q = hex_starts_qr[side].q*radius + hex_directions_qr[side].q*(ring-(radius*side)); + world->r = hex_starts_qr[side].r*radius + hex_directions_qr[side].r*(ring-(radius*side)); +} + +void region_qr(HexCoord region, HexCoord* world) { + world->q = region.q * REGION_DIAMETER + region.r * (REGION_DIAMETER - 1)/2; + world->r = -region.r * REGION_DIAMETER - region.q * (REGION_DIAMETER + 1)/2; +} + +void hex_add(HexCoord from, HexCoord* to) { + to->q += from.q; + to->r += from.r; +} + +unsigned int hex_distance(HexCoord a, HexCoord b) { + return (abs(a.q - b.q) + abs(a.r - b.r) + abs(a.q + a.r - b.q - b.r))/2; +} + +unsigned int region_radius_1(HexCoord hex, HexCoord region) { + return region.q*REGION_DIAMETER + region.r*(REGION_SIZE-1) - hex.q; +} + +unsigned int region_radius_2(HexCoord hex, HexCoord region) { + return -region.r*REGION_DIAMETER - region.q*REGION_SIZE - hex.r; +} + +unsigned int region_radius_3(HexCoord hex, HexCoord region) { + return region.q*(REGION_SIZE-1) - region.r*REGION_SIZE - hex.q - hex.r; +} + +void region_1(HexCoord hex, HexCoord* region) { + region->q = ceil((hex.q*REGION_DIAMETER + hex.r*(REGION_SIZE-1))/(double)REGION_HEX_COUNT); + region->r = floor((-hex.q*REGION_SIZE - hex.r*REGION_DIAMETER)/(double)REGION_HEX_COUNT); +} + +void region_2(HexCoord hex, HexCoord* region) { + region->q = ceil((hex.q*REGION_DIAMETER + hex.r*(REGION_SIZE - 1))/(double)REGION_HEX_COUNT); + region->r = floor((-hex.q*REGION_SIZE - hex.r*REGION_DIAMETER + REGION_SIZE*REGION_SIZE - 2*REGION_SIZE + 1)/(double)REGION_HEX_COUNT); +} + +void region_3(HexCoord hex, HexCoord* region) { + region->q = ceil((hex.q*REGION_DIAMETER + hex.r*(REGION_SIZE-1) - REGION_SIZE*REGION_SIZE + 2*REGION_SIZE - 1)/(double)REGION_HEX_COUNT); + region->r = ceil((-hex.q*REGION_SIZE - hex.r*REGION_DIAMETER)/(double)REGION_HEX_COUNT); +} + +void region_4(HexCoord hex, HexCoord* region) { + region->q = ceil((hex.q*REGION_DIAMETER + hex.r*(REGION_SIZE-1) - REGION_SIZE*REGION_SIZE + REGION_SIZE)/(double)REGION_HEX_COUNT); + region->r = floor((-hex.q*REGION_SIZE - hex.r*REGION_DIAMETER)/(double)REGION_HEX_COUNT); +} + +void region_5(HexCoord hex, HexCoord* region) { + region->q = ceil((hex.r*(REGION_SIZE-1) + hex.q*REGION_DIAMETER - 2*REGION_SIZE*REGION_SIZE + 2*REGION_SIZE)/(double)REGION_HEX_COUNT); + region->r = floor((-hex.q*REGION_SIZE - hex.r*REGION_DIAMETER + REGION_SIZE*REGION_SIZE - REGION_SIZE)/(double)REGION_HEX_COUNT); +} + +void region_6(HexCoord hex, HexCoord* region) { + region->q = floor((hex.q*REGION_DIAMETER + hex.r*(REGION_SIZE-1))/(double)REGION_HEX_COUNT); + region->r = ceil((-hex.q*REGION_SIZE - hex.r*REGION_DIAMETER)/(double)REGION_HEX_COUNT); +} + +void hex_index(HexCoord world, HexCoord* region, uint32_t* hex) { + int R1, R2, R3; + unsigned int side, radius; + HexCoord side_start, region_center; + + region_1(world, region); + R1 = region_radius_1(world, *region); + R2 = region_radius_2(world, *region); + R3 = region_radius_3(world, *region); + radius = (R1 + R2 + R3)/2; + if(R1 >= 0 && R2 > 0 && radius <= REGION_SIZE - 1) { + side = 0; + goto side_found; + } + + region_2(world, region); + R1 = region_radius_1(world, *region); + R2 = region_radius_2(world, *region); + R3 = region_radius_3(world, *region); + radius = (R1 - R2 + R3)/2; + if(R2 <= 0 && R3 > 0 && radius <= REGION_SIZE - 1) { + side = 1; + goto side_found; + } + + region_3(world, region); + R1 = region_radius_1(world, *region); + R2 = region_radius_2(world, *region); + R3 = region_radius_3(world, *region); + radius = (R1 - R2 - R3)/2; + if(R1 > 0 && R3 <= 0 && radius <= REGION_SIZE - 1) { + side = 2; + goto side_found; + } + + region_4(world, region); + R1 = region_radius_1(world, *region); + R2 = region_radius_2(world, *region); + R3 = region_radius_3(world, *region); + radius = (-R1 + R2 + R3)/2; + if(R1 < 0 && R3 >= 0 && radius <= REGION_SIZE - 1) { + side = 5; + goto side_found; + } + + region_5(world, region); + R1 = region_radius_1(world, *region); + R2 = region_radius_2(world, *region); + R3 = region_radius_3(world, *region); + radius = (-R1 + R2 - R3)/2; + if(R2 >= 0 && R3 < 0 && radius <= REGION_SIZE - 1) { + side = 4; + goto side_found; + } + + region_6(world, region); + side = 3; + R1 = region_radius_1(world, *region); + R2 = region_radius_2(world, *region); + R3 = region_radius_3(world, *region); + radius = (-R1 - R2 -R3)/2; + +side_found: + side_start.q = hex_starts_qr[side].q * radius; + side_start.r = hex_starts_qr[side].r * radius; + region_qr(*region, ®ion_center); + hex_add(region_center, &side_start); + + unsigned int side_distance = hex_distance(world, side_start); + if(radius == 0) { + *hex = 0; + } else { + *hex = (3*radius*(radius-1) + 1) + radius*side + side_distance; + } +}