From 75737b738f9884f3a918ccc3b071aeb07497e057 Mon Sep 17 00:00:00 2001 From: veclavtalica Date: Sun, 9 Mar 2025 00:30:20 +0300 Subject: [PATCH] /apps/tools/twndel: plane intersection based point move --- apps/tools/twndel/tool.c | 70 ++++++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 20 deletions(-) diff --git a/apps/tools/twndel/tool.c b/apps/tools/twndel/tool.c index 6c4df04..1d36ae1 100644 --- a/apps/tools/twndel/tool.c +++ b/apps/tools/twndel/tool.c @@ -222,6 +222,23 @@ static bool find_closest_point(uint8_t* object_result, uint16_t *point_result) { } +/* o = vector origin */ +/* v = vector direction, normalized */ +/* p = any point on plane */ +/* n = normal of a plane */ +static bool vector_plane_intersection(Vec3 o, Vec3 v, Vec3 p, Vec3 n, Vec3 *out) { + float dot = vec3_dot(n, v); + if (dot > FLT_EPSILON) { + Vec3 w = vec3_sub(o, p); + float fac = -vec3_dot(n, w) / dot; + *out = vec3_add(o, vec3_scale(v, fac)); + return true; + } + /* vector and plane are perpendicular, assume that it lies exactly on it */ + return false; +} + + static void process_operation_move_point(Operation *op) { /* finish dragging around */ /* TODO: dont keep empty ops on stack? */ @@ -238,33 +255,46 @@ static void process_operation_move_point(Operation *op) { (Color){255,255,255,255}, false); - DrawCameraUnprojectResult pos_and_ray = unproject_point(ctx.mouse_position); - + DrawCameraUnprojectResult cam = 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); + bool point_moved = false; /* TODO: show thresholds */ + /* TODO: planes used should depend on looking angle */ + /* for example, editing from the side makes better use of x/z facing planes */ - log_vec3(b, "cross"); + Vec3 s; + if (!state.axis_mask[0]) { + if (vector_plane_intersection(cam.position, cam.direction, p, (Vec3){0,copysignf(1,cam.direction.y),0}, &s)) { + int16_t xch = (int16_t)(floorf(vec3_dot(vec3_sub(s, p), (Vec3){1,0,0}) * (float)POINTS_PER_METER)); + xch -= xch % state.grid_snap_granularity; + state.points[op->data.move_point.point].x += xch; + op->data.move_point.delta_x += xch; + if (xch != 0) point_moved = true; + } + } - /* change along axes, delta is accumulated when threshold is met*/ - int16_t xch = (int16_t)(floorf(vec3_dot(b, (Vec3){0,0,1}) * (float)POINTS_PER_METER)) * !state.axis_mask[0]; - xch -= xch % state.grid_snap_granularity; - state.points[op->data.move_point.point].x += xch; - op->data.move_point.delta_x += xch; + if (!state.axis_mask[1]) { + if (vector_plane_intersection(cam.position, cam.direction, p, (Vec3){0,0,copysignf(1,cam.direction.z)}, &s)) { + int16_t ych = (int16_t)(floorf(vec3_dot(vec3_sub(s, p), (Vec3){0,1,0}) * (float)POINTS_PER_METER)); + ych -= ych % state.grid_snap_granularity; + state.points[op->data.move_point.point].y += ych; + op->data.move_point.delta_y += ych; + if (ych != 0) point_moved = true; + } + } - int16_t ych = (int16_t)(floorf(vec3_dot(vec3_cross(b, pos_and_ray.direction), (Vec3){0,-1,0}) * (float)POINTS_PER_METER)) * !state.axis_mask[1]; - ych -= ych % state.grid_snap_granularity; - state.points[op->data.move_point.point].y += ych; - op->data.move_point.delta_y += ych; + if (!state.axis_mask[2]) { + if (vector_plane_intersection(cam.position, cam.direction, p, (Vec3){0,copysignf(1,cam.direction.y),0}, &s)) { + int16_t zch = (int16_t)(floorf(vec3_dot(vec3_sub(s, p), (Vec3){0,0,1}) * (float)POINTS_PER_METER)); + zch -= zch % state.grid_snap_granularity; + state.points[op->data.move_point.point].z += zch; + op->data.move_point.delta_z += zch; + if (zch != 0) point_moved = true; + } + } - int16_t zch = (int16_t)(floorf(vec3_dot(b, (Vec3){-1,0,0}) * (float)POINTS_PER_METER)) * !state.axis_mask[2]; - zch -= zch % state.grid_snap_granularity; - state.points[op->data.move_point.point].z += zch; - op->data.move_point.delta_z += zch; - - if (xch != 0 || ych != 0 || zch != 0) + if (point_moved) audio_play("/data/bong.ogg", NULL, false, 0.12f, 0.0f); }