Made color/height modification also modify neighbors. Need to change highlight pipeline to allow for CPU-defined highlights.

main
noah metz 2024-11-24 19:40:49 -07:00
parent 4e0cae59ca
commit f2af2b8055
3 changed files with 221 additions and 95 deletions

@ -34,8 +34,7 @@ typedef struct GPUHexStruct {
} GPUHex; } GPUHex;
typedef struct GPUHexRegionStruct { typedef struct GPUHexRegionStruct {
int32_t q; HexCoord position;
int32_t r;
int32_t y; int32_t y;
uint32_t map; uint32_t map;
@ -106,6 +105,11 @@ VkResult allocate_hex_region(
HexContext* hex, HexContext* hex,
RenderContext* gpu); RenderContext* gpu);
VkResult free_hex_region(
uint32_t region_index,
HexContext* hex,
RenderContext* gpu);
bool ray_world_intersect( bool ray_world_intersect(
float* distance, float* distance,
uint32_t* vertex, uint32_t* vertex,
@ -144,4 +148,11 @@ void hex_add(HexCoord from, HexCoord* to);
void hex_index(HexCoord world, HexCoord* region, uint32_t* hex); void hex_index(HexCoord world, HexCoord* region, uint32_t* hex);
void hex_vertex_neighbors(
uint32_t vertex, HexCoord hex,
uint32_t n_vertex[2], HexCoord n_region[2], uint32_t n_hex[2]);
void first_matching_region(HexCoord coord, int y, uint32_t* region, HexContext* context);
#endif #endif

@ -1,6 +1,8 @@
#include <stdio.h> #include <stdio.h>
#include "hex.h"
#include "hsv.h" #include "hsv.h"
#include "engine.h" #include "engine.h"
#include "vulkan/vulkan_core.h"
#include <math.h> #include <math.h>
#include <stdlib.h> #include <stdlib.h>
@ -8,7 +10,6 @@
#define COLOR_PICK_CONTAINER_ID 0x03 #define COLOR_PICK_CONTAINER_ID 0x03
typedef struct EditorDataStruct { typedef struct EditorDataStruct {
uint32_t selected_region; uint32_t selected_region;
uint32_t last_selected_region;
uint32_t last_clicked_region; uint32_t last_clicked_region;
uint32_t last_clicked_hex; uint32_t last_clicked_hex;
@ -29,6 +30,35 @@ uint32_t hex_color(vec4 color) {
+ ((lrint(color[3]*255.0) & 0xFF) << 0); + ((lrint(color[3]*255.0) & 0xFF) << 0);
} }
VkResult set_vertex_height(float height, uint32_t region, uint32_t hex, uint32_t vertex, ClientContext* context) {
if(vertex == 0) return VK_ERROR_VALIDATION_FAILED_EXT;
context->hex.regions[region]->data.hexes[hex].height[vertex-1] = height;
return add_transfer(
&context->hex.regions[region]->data.hexes[hex].height[vertex-1],
context->hex.regions[region]->region,
offsetof(GPUHexRegion, hexes)
+ sizeof(GPUHex)*hex
+ offsetof(GPUHex, height)
+ sizeof(float)*(vertex-1),
sizeof(float),
context->render.current_frame,
&context->render);
}
VkResult set_vertex_color(vec4 color, uint32_t region, uint32_t hex, uint32_t vertex, ClientContext* context) {
context->hex.regions[region]->data.hexes[hex].color[vertex] = hex_color(color);
return add_transfer(
&context->hex.regions[region]->data.hexes[hex].color[vertex],
context->hex.regions[region]->region,
offsetof(GPUHexRegion, hexes)
+ sizeof(GPUHex)*hex
+ offsetof(GPUHex, color)
+ sizeof(uint32_t)*vertex,
sizeof(uint32_t),
context->render.current_frame,
&context->render);
}
uint32_t add_hex_region(ClientContext* context) { uint32_t add_hex_region(ClientContext* context) {
HexRegion* region; HexRegion* region;
@ -834,12 +864,13 @@ VkResult update_region_info_ui(ClientContext* context) {
EditorData* data = context->app_data; EditorData* data = context->app_data;
HexRegion* selected_region = context->hex.regions[data->selected_region]; HexRegion* selected_region = context->hex.regions[data->selected_region];
if(selected_region == NULL) {
snprintf(temp, snprintf(temp,
sizeof(temp), sizeof(temp),
"Region %4d", data->selected_region); "");
VK_RESULT(update_ui_string(temp, 0x01, 0, 0, &context->ui, &context->render)); VK_RESULT(update_ui_string(temp, 0x01, 0, 0, &context->ui, &context->render));
if(selected_region == NULL) {
snprintf( snprintf(
temp, temp,
sizeof(temp), sizeof(temp),
@ -858,16 +889,21 @@ VkResult update_region_info_ui(ClientContext* context) {
""); "");
VK_RESULT(update_ui_string(temp, 0x01, 0, 3, &context->ui, &context->render)); VK_RESULT(update_ui_string(temp, 0x01, 0, 3, &context->ui, &context->render));
} else { } else {
snprintf(temp,
sizeof(temp),
"Region %4d", data->selected_region);
VK_RESULT(update_ui_string(temp, 0x01, 0, 0, &context->ui, &context->render));
snprintf( snprintf(
temp, temp,
sizeof(temp), sizeof(temp),
"Q: %4d", selected_region->data.q); "Q: %4d", selected_region->data.position.q);
VK_RESULT(update_ui_string(temp, 0x01, 0, 1, &context->ui, &context->render)); VK_RESULT(update_ui_string(temp, 0x01, 0, 1, &context->ui, &context->render));
snprintf( snprintf(
temp, temp,
sizeof(temp), sizeof(temp),
"R: %4d", selected_region->data.r); "R: %4d", selected_region->data.position.r);
VK_RESULT(update_ui_string(temp, 0x01, 0, 2, &context->ui, &context->render)); VK_RESULT(update_ui_string(temp, 0x01, 0, 2, &context->ui, &context->render));
snprintf( snprintf(
@ -943,14 +979,12 @@ VkResult update_hex_info_ui(ClientContext* context) {
context->hex.data.clicked_hex); context->hex.data.clicked_hex);
VK_RESULT(update_ui_string(temp, 0x02, 0, 0, &context->ui, &context->render)); VK_RESULT(update_ui_string(temp, 0x02, 0, 0, &context->ui, &context->render));
HexCoord hex_world; HexCoord hex_world;
hex_qr(context->hex.data.clicked_hex, &hex_world); hex_qr(context->hex.data.clicked_hex, &hex_world);
HexCoord region_coord = {region->data.q, region->data.r}; HexCoord region_coord = {region->data.position.q, region->data.position.r};
HexCoord region_world; HexCoord region_world;
region_qr(region_coord, &region_world); region_qr(region_coord, &region_world);
hex_add(region_world, &hex_world); hex_add(region_world, &hex_world);
snprintf( snprintf(
@ -1010,7 +1044,7 @@ VkResult update_hex_info_ui(ClientContext* context) {
} }
bool editor_key_callback(ClientContext* context, int key, int action, int mods) { bool editor_key_callback(ClientContext* context, int key, int action, int mods) {
(void)mods; uint32_t start, next_region;
if(action != GLFW_PRESS) return false; if(action != GLFW_PRESS) return false;
@ -1020,28 +1054,59 @@ bool editor_key_callback(ClientContext* context, int key, int action, int mods)
switch(key) { switch(key) {
case GLFW_KEY_EQUAL: case GLFW_KEY_EQUAL:
data->selected_region = add_hex_region(context); data->selected_region = add_hex_region(context);
update_region_info_ui(context);
update_hex_info_ui(context);
break; break;
case GLFW_KEY_LEFT_BRACKET: case GLFW_KEY_MINUS:
data->selected_region -= 1; free_hex_region(data->selected_region, &context->hex, &context->render);
if(data->selected_region > MAX_LOADED_REGIONS) { start = data->selected_region;
next_region = start;
do {
next_region -= 1;
if(next_region > MAX_LOADED_REGIONS) next_region = MAX_LOADED_REGIONS;
if(next_region != MAX_LOADED_REGIONS && context->hex.regions[next_region] != NULL) break;
} while(next_region != start);
if(next_region == start) {
data->selected_region = MAX_LOADED_REGIONS; data->selected_region = MAX_LOADED_REGIONS;
} else {
data->selected_region = next_region;
} }
update_region_info_ui(context);
update_hex_info_ui(context);
break;
case GLFW_KEY_LEFT_BRACKET:
start = data->selected_region;
next_region = start;
do {
next_region -= 1;
if(next_region > MAX_LOADED_REGIONS) next_region = MAX_LOADED_REGIONS;
if(next_region != MAX_LOADED_REGIONS && context->hex.regions[next_region] != NULL) break;
} while(next_region != start);
data->selected_region = next_region;
update_region_info_ui(context);
break; break;
case GLFW_KEY_RIGHT_BRACKET: case GLFW_KEY_RIGHT_BRACKET:
data->selected_region += 1; start = data->selected_region;
if(data->selected_region > MAX_LOADED_REGIONS) { next_region = start;
data->selected_region = 0; do {
} next_region += 1;
if(next_region > MAX_LOADED_REGIONS) next_region = 0;
if(next_region != MAX_LOADED_REGIONS && context->hex.regions[next_region] != NULL) break;
} while(next_region != start);
data->selected_region = next_region;
update_region_info_ui(context);
break; break;
case GLFW_KEY_I: case GLFW_KEY_I:
if(context->hex.regions[data->selected_region] != NULL) { if(context->hex.regions[data->selected_region] != NULL) {
context->hex.regions[data->selected_region]->data.q += 1; context->hex.regions[data->selected_region]->data.position.q += 1;
add_transfer( add_transfer(
&context->hex.regions[data->selected_region]->data.q, &context->hex.regions[data->selected_region]->data.position,
context->hex.regions[data->selected_region]->region, context->hex.regions[data->selected_region]->region,
offsetof(GPUHexRegion, q), offsetof(GPUHexRegion, position),
sizeof(uint32_t), sizeof(uint32_t),
context->render.current_frame, context->render.current_frame,
&context->render); &context->render);
@ -1050,11 +1115,11 @@ bool editor_key_callback(ClientContext* context, int key, int action, int mods)
break; break;
case GLFW_KEY_K: case GLFW_KEY_K:
if(context->hex.regions[data->selected_region] != NULL) { if(context->hex.regions[data->selected_region] != NULL) {
context->hex.regions[data->selected_region]->data.q -= 1; context->hex.regions[data->selected_region]->data.position.q -= 1;
add_transfer( add_transfer(
&context->hex.regions[data->selected_region]->data.q, &context->hex.regions[data->selected_region]->data.position.q,
context->hex.regions[data->selected_region]->region, context->hex.regions[data->selected_region]->region,
offsetof(GPUHexRegion, q), offsetof(GPUHexRegion, position) + offsetof(HexCoord, q),
sizeof(uint32_t), sizeof(uint32_t),
context->render.current_frame, context->render.current_frame,
&context->render); &context->render);
@ -1063,11 +1128,11 @@ bool editor_key_callback(ClientContext* context, int key, int action, int mods)
break; break;
case GLFW_KEY_J: case GLFW_KEY_J:
if(context->hex.regions[data->selected_region] != NULL) { if(context->hex.regions[data->selected_region] != NULL) {
context->hex.regions[data->selected_region]->data.r += 1; context->hex.regions[data->selected_region]->data.position.r += 1;
add_transfer( add_transfer(
&context->hex.regions[data->selected_region]->data.r, &context->hex.regions[data->selected_region]->data.position.r,
context->hex.regions[data->selected_region]->region, context->hex.regions[data->selected_region]->region,
offsetof(GPUHexRegion, r), offsetof(GPUHexRegion, position) + offsetof(HexCoord, r),
sizeof(uint32_t), sizeof(uint32_t),
context->render.current_frame, context->render.current_frame,
&context->render); &context->render);
@ -1076,11 +1141,11 @@ bool editor_key_callback(ClientContext* context, int key, int action, int mods)
break; break;
case GLFW_KEY_L: case GLFW_KEY_L:
if(context->hex.regions[data->selected_region] != NULL) { if(context->hex.regions[data->selected_region] != NULL) {
context->hex.regions[data->selected_region]->data.r -= 1; context->hex.regions[data->selected_region]->data.position.r -= 1;
add_transfer( add_transfer(
&context->hex.regions[data->selected_region]->data.r, &context->hex.regions[data->selected_region]->data.position.r,
context->hex.regions[data->selected_region]->region, context->hex.regions[data->selected_region]->region,
offsetof(GPUHexRegion, r), offsetof(GPUHexRegion, position) + offsetof(HexCoord, r),
sizeof(uint32_t), sizeof(uint32_t),
context->render.current_frame, context->render.current_frame,
&context->render); &context->render);
@ -1116,35 +1181,54 @@ bool editor_key_callback(ClientContext* context, int key, int action, int mods)
case GLFW_KEY_Y: case GLFW_KEY_Y:
region = context->hex.regions[context->hex.data.clicked_region]; region = context->hex.regions[context->hex.data.clicked_region];
if(region != NULL) { if(region != NULL && context->hex.data.clicked_vertex != 0) {
region->data.hexes[context->hex.data.clicked_hex].height[context->hex.data.clicked_vertex-1] += 0.1; float height = region->data.hexes[context->hex.data.clicked_hex].height[context->hex.data.clicked_vertex-1] + 0.1;
add_transfer(
&region->data.hexes[context->hex.data.clicked_hex].height[context->hex.data.clicked_vertex-1], if(~mods & GLFW_MOD_CONTROL) {
region->region, uint32_t n_vertex[2], n_hex[2];
offsetof(GPUHexRegion, hexes) HexCoord n_region[2];
+ sizeof(GPUHex)*context->hex.data.clicked_hex HexCoord world, region_center;
+ offsetof(GPUHex, height)
+ sizeof(float)*(context->hex.data.clicked_vertex-1), region_qr(region->data.position, &region_center);
sizeof(float), hex_qr(context->hex.data.clicked_hex, &world);
context->render.current_frame, hex_add(region_center, &world);
&context->render); hex_vertex_neighbors(context->hex.data.clicked_vertex, world, n_vertex, n_region, n_hex);
uint32_t n0, n1;
first_matching_region(n_region[0], region->data.y, &n0, &context->hex);
first_matching_region(n_region[1], region->data.y, &n1, &context->hex);
if(n0 != MAX_LOADED_REGIONS) set_vertex_height(height, n0, n_hex[0], n_vertex[0], context);
if(n1 != MAX_LOADED_REGIONS) set_vertex_height(height, n1, n_hex[1], n_vertex[1], context);
}
set_vertex_height(height, context->hex.data.clicked_region, context->hex.data.clicked_hex, context->hex.data.clicked_vertex, context);
update_hex_info_ui(context); update_hex_info_ui(context);
} }
break; break;
case GLFW_KEY_H: case GLFW_KEY_H:
region = context->hex.regions[context->hex.data.clicked_region]; region = context->hex.regions[context->hex.data.clicked_region];
if(region != NULL) { if(region != NULL && context->hex.data.clicked_vertex != 0) {
region->data.hexes[context->hex.data.clicked_hex].height[context->hex.data.clicked_vertex-1] -= 0.1; float height = region->data.hexes[context->hex.data.clicked_hex].height[context->hex.data.clicked_vertex-1] - 0.1;
add_transfer(
&region->data.hexes[context->hex.data.clicked_hex].height[context->hex.data.clicked_vertex-1], if(~mods & GLFW_MOD_CONTROL) {
region->region, uint32_t n_vertex[2], n_hex[2];
offsetof(GPUHexRegion, hexes) HexCoord n_region[2];
+ sizeof(GPUHex)*context->hex.data.clicked_hex HexCoord world, region_center;
+ offsetof(GPUHex, height)
+ sizeof(float)*(context->hex.data.clicked_vertex-1), region_qr(region->data.position, &region_center);
sizeof(float), hex_qr(context->hex.data.clicked_hex, &world);
context->render.current_frame, hex_add(region_center, &world);
&context->render); hex_vertex_neighbors(context->hex.data.clicked_vertex, world, n_vertex, n_region, n_hex);
uint32_t n0, n1;
first_matching_region(n_region[0], region->data.y, &n0, &context->hex);
first_matching_region(n_region[1], region->data.y, &n1, &context->hex);
if(n0 != MAX_LOADED_REGIONS) set_vertex_height(height, n0, n_hex[0], n_vertex[0], context);
if(n1 != MAX_LOADED_REGIONS) set_vertex_height(height, n1, n_hex[1], n_vertex[1], context);
}
set_vertex_height(height, context->hex.data.clicked_region, context->hex.data.clicked_hex, context->hex.data.clicked_vertex, context);
update_hex_info_ui(context); update_hex_info_ui(context);
} }
break; break;
@ -1152,17 +1236,24 @@ bool editor_key_callback(ClientContext* context, int key, int action, int mods)
case GLFW_KEY_E: case GLFW_KEY_E:
region = context->hex.regions[context->hex.data.clicked_region]; region = context->hex.regions[context->hex.data.clicked_region];
if(region != NULL) { if(region != NULL) {
region->data.hexes[context->hex.data.clicked_hex].color[context->hex.data.clicked_vertex] = hex_color(data->current); uint32_t n_vertex[2], n_hex[2];
add_transfer( HexCoord n_region[2];
&region->data.hexes[context->hex.data.clicked_hex].color[context->hex.data.clicked_vertex], HexCoord world, region_center;
region->region,
offsetof(GPUHexRegion, hexes) if(context->hex.data.clicked_vertex != 0) {
+ sizeof(GPUHex)*context->hex.data.clicked_hex region_qr(region->data.position, &region_center);
+ offsetof(GPUHex, color) hex_qr(context->hex.data.clicked_hex, &world);
+ sizeof(uint32_t)*(context->hex.data.clicked_vertex), hex_add(region_center, &world);
sizeof(uint32_t), hex_vertex_neighbors(context->hex.data.clicked_vertex, world, n_vertex, n_region, n_hex);
context->render.current_frame,
&context->render); uint32_t n0, n1;
first_matching_region(n_region[0], region->data.y, &n0, &context->hex);
first_matching_region(n_region[1], region->data.y, &n1, &context->hex);
if(n0 != MAX_LOADED_REGIONS) set_vertex_color(data->current, n0, n_hex[0], n_vertex[0], context);
if(n1 != MAX_LOADED_REGIONS) set_vertex_color(data->current, n1, n_hex[1], n_vertex[1], context);
}
set_vertex_color(data->current, context->hex.data.clicked_region, context->hex.data.clicked_hex, context->hex.data.clicked_vertex, context);
update_hex_info_ui(context); update_hex_info_ui(context);
} }
break; break;
@ -1181,11 +1272,6 @@ void editor_frame(ClientContext* context) {
data->last_clicked_vertex = context->hex.data.clicked_vertex; data->last_clicked_vertex = context->hex.data.clicked_vertex;
update_hex_info_ui(context); update_hex_info_ui(context);
} }
if(data->selected_region != data->last_selected_region) {
data->last_selected_region = data->selected_region;
update_region_info_ui(context);
}
} }
void editor_startup(ClientContext* context) { void editor_startup(ClientContext* context) {
@ -1194,22 +1280,6 @@ void editor_startup(ClientContext* context) {
color_ui(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, &region_world);
hex_qr(hex, &hex_world);
hex_add(region_world, &hex_world);
hex_add(hex_world, &n1);
hex_add(hex_world, &n2);
}
int main() { int main() {
EditorData* data = malloc(sizeof(EditorData)); EditorData* data = malloc(sizeof(EditorData));
memset(data, 0, sizeof(EditorData)); memset(data, 0, sizeof(EditorData));

@ -759,6 +759,24 @@ VkResult set_hex_region(HexRegion* region, HexContext* hex, RenderContext* gpu)
gpu); gpu);
} }
VkResult free_hex_region(
uint32_t region_index,
HexContext* hex,
RenderContext* gpu) {
if(hex->regions[region_index] == NULL) return VK_ERROR_VALIDATION_FAILED_EXT;
free(hex->regions[region_index]);
hex->regions[region_index] = NULL;
VkDeviceAddress null_address = 0x00;
return add_transfers(
&null_address,
hex->context,
offsetof(GPUHexContext, regions) + sizeof(VkDeviceAddress)*region_index,
sizeof(VkDeviceAddress),
gpu);
}
VkResult allocate_hex_region( VkResult allocate_hex_region(
int32_t q, int32_t q,
int32_t r, int32_t r,
@ -782,8 +800,8 @@ VkResult allocate_hex_region(
return VK_ERROR_OUT_OF_HOST_MEMORY; return VK_ERROR_OUT_OF_HOST_MEMORY;
} }
(*region)->data.q = q; (*region)->data.position.q = q;
(*region)->data.r = r; (*region)->data.position.r = r;
(*region)->data.y = y; (*region)->data.y = y;
(*region)->data.map = map; (*region)->data.map = map;
VK_RESULT(create_storage_buffer( VK_RESULT(create_storage_buffer(
@ -793,9 +811,9 @@ VkResult allocate_hex_region(
&(*region)->region, &(*region)->region,
&(*region)->region_memory)); &(*region)->region_memory));
VK_RESULT(add_transfer( VK_RESULT(add_transfer(
&(*region)->data.q, &(*region)->data.position,
(*region)->region, (*region)->region,
offsetof(GPUHexRegion, q), offsetof(GPUHexRegion, position),
sizeof(int32_t)*3 + sizeof(uint32_t), sizeof(int32_t)*3 + sizeof(uint32_t),
gpu->current_frame, gpu->current_frame,
gpu)); gpu));
@ -920,9 +938,9 @@ bool ray_region_intersect(
float intersect_distance = INFINITY; float intersect_distance = INFINITY;
uint32_t intersection_vertex = 0; uint32_t intersection_vertex = 0;
vec3 region_offset = { vec3 region_offset = {
((float)region->data.q + (float)region->data.r/2)*REGION_WIDTH - region->data.r*HEX_X/2, ((float)region->data.position.q + (float)region->data.position.r/2)*REGION_WIDTH - region->data.position.r*HEX_X/2,
0, 0,
0.75*region->data.r*REGION_HEIGHT + 0.25*region->data.r*HEX_Z + 0.5*region->data.q*HEX_Z, 0.75*region->data.position.r*REGION_HEIGHT + 0.25*region->data.position.r*HEX_Z + 0.5*region->data.position.q*HEX_Z,
}; };
for(uint32_t intersect_hid = 0; intersect_hid < REGION_HEX_COUNT; intersect_hid++) { for(uint32_t intersect_hid = 0; intersect_hid < REGION_HEX_COUNT; intersect_hid++) {
@ -1277,3 +1295,30 @@ side_found:
*hex = (3*radius*(radius-1) + 1) + radius*side + side_distance; *hex = (3*radius*(radius-1) + 1) + radius*side + side_distance;
} }
} }
void hex_vertex_neighbors(
uint32_t vertex, HexCoord hex,
uint32_t n_vertex[2], HexCoord n_region[2], uint32_t n_hex[2]) {
HexCoord n1 = hex_starts_qr[(vertex+3) % 6];
HexCoord n2 = hex_starts_qr[(vertex+4) % 6];
hex_add(hex, &n1);
hex_add(hex, &n2);
hex_index(n1, &n_region[0], &n_hex[0]);
hex_index(n2, &n_region[1], &n_hex[1]);
n_vertex[0] = ((vertex + 1) % 6) + 1;
n_vertex[1] = ((vertex + 3) % 6) + 1;
}
void first_matching_region(HexCoord coord, int y, uint32_t* region, HexContext* context) {
for(*region = 0; *region < MAX_LOADED_REGIONS; (*region)++) {
if(context->regions[*region] != NULL
&& context->regions[*region]->data.position.q == coord.q
&& context->regions[*region]->data.position.r == coord.r
&& context->regions[*region]->data.y == y) {
return;
}
}
}