From c07e16490ed71f07f61447abd47c0210a8ea3fe4 Mon Sep 17 00:00:00 2001 From: veclavtalica Date: Sat, 8 Mar 2025 00:50:47 +0300 Subject: [PATCH] model tool progress: initial selection --- apps/tools/twndel/state.h | 9 ++-- apps/tools/twndel/tool.c | 102 ++++++++++++++++++++++++++++++++------ src/rendering/twn_draw.c | 21 ++------ 3 files changed, 97 insertions(+), 35 deletions(-) diff --git a/apps/tools/twndel/state.h b/apps/tools/twndel/state.h index 09a776e..1acf518 100644 --- a/apps/tools/twndel/state.h +++ b/apps/tools/twndel/state.h @@ -27,9 +27,11 @@ typedef struct Operation { } kind; union { struct { - uint16_t id; + uint16_t point; int16_t delta_x; int16_t delta_y; + int16_t delta_z; + uint8_t object; } move_point; } data; } Operation; @@ -58,8 +60,9 @@ typedef struct Object { } Object; typedef struct State { - Operation undo_stack[UNDO_STACK_SIZE]; - uint32_t undo_stack_ptr; + Operation op_stack[UNDO_STACK_SIZE]; + uint32_t op_stack_ptr; + bool op_active; Vec3 camera_position; Vec3 camera_direction; diff --git a/apps/tools/twndel/tool.c b/apps/tools/twndel/tool.c index 7da5a02..42b9914 100644 --- a/apps/tools/twndel/tool.c +++ b/apps/tools/twndel/tool.c @@ -40,7 +40,7 @@ static uint16_t new_point(int16_t x, int16_t y, int16_t z) { static uint16_t push_face(uint8_t object, uint16_t p0, uint16_t p1, uint16_t p2, uint16_t p3, uint8_t texture) { Object *o = &state.objects[object]; o->faces_sz++; - o->faces[o->faces_sz-1] = (Face) {p0, p1, p2, p3, texture}; + o->faces[o->faces_sz-1] = (Face) {.p = {p0, p1, p2, p3}, .texture = texture}; return o->faces_sz-1; } @@ -54,6 +54,14 @@ static uint8_t push_texture(uint8_t object, char *texture) { } +static void push_operation(Operation operation, bool active) { + state.op_stack_ptr++; + uint8_t op = state.op_stack_ptr % UNDO_STACK_SIZE; + state.op_stack[op] = operation; + state.op_active = active; +} + + static inline Vec3 point_to_vec3(uint8_t object, uint16_t point) { Object *o = &state.objects[object]; return (Vec3){ (o->position.x + state.points[point].x) / (float)POINTS_PER_METER, @@ -147,22 +155,28 @@ static void process_camera_movement(void) { Vec3 new_rot = vec3_rotate(state.camera_direction, vertical_rotation, front); /* only apply if it's in limits */ - if (fabsf(vec3_dot(new_rot, (Vec3){0,-1,0})) <= 0.99f) { + float d = vec3_dot(new_rot, (Vec3){0,-1,0}); + if (fabsf(d) <= 0.999f) { state.camera_position = vec3_rotate(state.camera_position, vertical_rotation, front); state.camera_direction = new_rot; } } -static bool find_closest_point(uint8_t* object_result, uint16_t *point_result) { - DrawCameraUnprojectResult pos_and_ray = draw_camera_unproject( - ctx.mouse_position, +static inline DrawCameraUnprojectResult unproject_point(Vec2 point) { + return draw_camera_unproject( + point, state.camera_position, state.camera_direction, (Vec3){0, 1, 0}, state.camera_is_orthographic ? 0 : CAMERA_FOV, state.camera_zoom, 100 ); +} + + +static bool find_closest_point(uint8_t* object_result, uint16_t *point_result) { + DrawCameraUnprojectResult pos_and_ray = unproject_point(ctx.mouse_position); /* step over every selectable object and find points closest to the view ray */ /* by constructing triangles and finding their height, from perpendicular */ @@ -209,19 +223,85 @@ static bool find_closest_point(uint8_t* object_result, uint16_t *point_result) { } +static void process_operation_move_point(Operation *op) { + /* finish dragging around */ + if (input_action_just_released("select")) { + state.op_active = false; + return; + } + + float size = sinf(ctx.frame_number / 10) * 0.05f + 0.05f; + draw_billboard("/data/grab.png", + point_to_vec3(op->data.move_point.object, op->data.move_point.point), + (Vec2){size, size}, + (Rect){0,0,16,16}, + (Color){255,255,255,255}, + false); + + DrawCameraUnprojectResult pos_and_ray = unproject_point(ctx.mouse_position); + + Vec3 p = point_to_vec3(op->data.move_point.object, op->data.move_point.point); + Vec3 d = vec3_sub(pos_and_ray.position, p); + Vec3 b = vec3_cross(d, pos_and_ray.direction); + + /* TODO: show thresholds */ + + /* change along axes, delta is accumulated when threshold is met*/ + int16_t zch = (int16_t)(floorf(vec3_dot(b, (Vec3){0,0,1}) * (float)POINTS_PER_METER)); + op->data.move_point.delta_x += zch; + state.points[op->data.move_point.point].x += zch; +} + + +static void process_operations(void) { + if (!state.op_active) { + uint16_t point_select; uint8_t obj_select; + if (find_closest_point(&obj_select, &point_select)) { + draw_billboard("/data/point.png", + point_to_vec3(obj_select, point_select), + (Vec2){0.05f, 0.05f}, + (Rect){0,0,16,16}, + (Color){255,255,255,255}, + false); + + if (input_action_just_pressed("select")) + push_operation((Operation){ + .kind = OPERATION_MOVE_POINT, + .data = { .move_point = { .point = point_select } }, + }, true ); + } + } + + if (state.op_active) { + Operation *op = &state.op_stack[state.op_stack_ptr % UNDO_STACK_SIZE]; + switch (op->kind) { + case OPERATION_MOVE_POINT: { + process_operation_move_point(op); + + break; + } + default: + (void)0; + } + } +} + + void game_tick(void) { if (!init) { /* default state */ new_cube((Point){0,0,0}, (Point){POINTS_PER_METER,POINTS_PER_METER,POINTS_PER_METER}); state.camera_position = (Vec3){2,1,2}; state.camera_direction = vec3_norm(((Vec3){-2,-1,-2})); - state.camera_zoom = 1.0f; + state.camera_zoom = 0.5f; init = true; } input_action("toggle_display_mode", "Q"); input_action("toggle_projection", "E"); + input_action("select", "LCLICK"); + if (input_action_just_pressed("toggle_display_mode")) { audio_play("/data/click.wav", NULL, false, 0.7f, 0.0f); state.solid_display_mode = !state.solid_display_mode; @@ -233,15 +313,7 @@ void game_tick(void) { } process_camera_movement(); - - uint16_t point_select; uint8_t obj_select; - if (find_closest_point(&obj_select, &point_select)) - draw_billboard("/data/point.png", - point_to_vec3(obj_select, point_select), - (Vec2){0.05f, 0.05f}, - (Rect){0,0,16,16}, - (Color){255,255,255,255}, - false); + process_operations(); /* axis helpers */ /* idea: black out inactives when dragging points */ diff --git a/src/rendering/twn_draw.c b/src/rendering/twn_draw.c index b0425fe..ed68e72 100644 --- a/src/rendering/twn_draw.c +++ b/src/rendering/twn_draw.c @@ -437,9 +437,6 @@ void draw_camera(Vec3 position, Vec3 direction, Vec3 up, float fov, float zoom, if (!orthographic && fov >= (float)(M_PI)) log_warn("Invalid fov given (%f)", (double)fov); - /* inital zoom = 1.0 correlates to perspective from this */ - zoom *= 0.1f; - float const aspect = (float)ctx.base_render_width / (float)ctx.base_render_height; Camera const camera = { @@ -448,8 +445,8 @@ void draw_camera(Vec3 position, Vec3 direction, Vec3 up, float fov, float zoom, .target = vec3_norm(direction), .up = up, .viewbox = { - aspect/-zoom, aspect/zoom, - 1/zoom, 1/-zoom + -aspect/zoom, aspect/zoom, + 1/zoom, -1/zoom }, .far_z = draw_distance }; @@ -511,9 +508,6 @@ DrawCameraUnprojectResult draw_camera_unproject(Vec2 point, if (!orthographic && fov >= (float)(M_PI)) log_warn("Invalid fov given (%f)", (double)fov); - /* inital zoom = 1.0 correlates to perspective from this */ - zoom *= 0.1f; - float const aspect = (float)ctx.base_render_width / (float)ctx.base_render_height; Camera const camera = { .fov = fov, @@ -521,8 +515,8 @@ DrawCameraUnprojectResult draw_camera_unproject(Vec2 point, .target = vec3_norm(direction), .up = up, .viewbox = { - aspect/-zoom, aspect/zoom, - 1/zoom, 1/-zoom + -aspect/zoom, aspect/zoom, + 1/zoom, -1/zoom }, .far_z = draw_distance }; @@ -534,13 +528,6 @@ DrawCameraUnprojectResult draw_camera_unproject(Vec2 point, point.y = (float)ctx.base_render_height - point.y; - if (!orthographic) { - point = (Vec2) { - point.x, - point.y, - }; - } - Vec4 v; v.x = 2.0f * point.x / (float)ctx.base_render_width - 1.0f; v.y = 2.0f * point.y / (float)ctx.base_render_height - 1.0f;