/apps/tools/twndel: plane intersection based point move
This commit is contained in:
		| @@ -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) { | static void process_operation_move_point(Operation *op) { | ||||||
|     /* finish dragging around */ |     /* finish dragging around */ | ||||||
|     /* TODO: dont keep empty ops on stack? */ |     /* TODO: dont keep empty ops on stack? */ | ||||||
| @@ -238,33 +255,46 @@ static void process_operation_move_point(Operation *op) { | |||||||
|                    (Color){255,255,255,255}, |                    (Color){255,255,255,255}, | ||||||
|                    false); |                    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 p = point_to_vec3(op->data.move_point.object, op->data.move_point.point); | ||||||
|     Vec3 d = vec3_sub(pos_and_ray.position, p); |     bool point_moved = false; | ||||||
|     Vec3 b = vec3_cross(d, pos_and_ray.direction); |  | ||||||
|  |  | ||||||
|     /* TODO: show thresholds */ |     /* 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*/ |     if (!state.axis_mask[1]) { | ||||||
|     int16_t xch = (int16_t)(floorf(vec3_dot(b, (Vec3){0,0,1}) * (float)POINTS_PER_METER)) * !state.axis_mask[0]; |         if (vector_plane_intersection(cam.position, cam.direction, p, (Vec3){0,0,copysignf(1,cam.direction.z)}, &s)) { | ||||||
|     xch -= xch % state.grid_snap_granularity; |             int16_t ych = (int16_t)(floorf(vec3_dot(vec3_sub(s, p), (Vec3){0,1,0}) * (float)POINTS_PER_METER)); | ||||||
|     state.points[op->data.move_point.point].x += xch; |             ych -= ych % state.grid_snap_granularity; | ||||||
|     op->data.move_point.delta_x += xch; |             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]; |     if (!state.axis_mask[2]) { | ||||||
|     ych -= ych % state.grid_snap_granularity; |         if (vector_plane_intersection(cam.position, cam.direction, p, (Vec3){0,copysignf(1,cam.direction.y),0}, &s)) { | ||||||
|     state.points[op->data.move_point.point].y += ych; |             int16_t zch = (int16_t)(floorf(vec3_dot(vec3_sub(s, p), (Vec3){0,0,1}) * (float)POINTS_PER_METER)); | ||||||
|     op->data.move_point.delta_y += ych; |             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]; |     if (point_moved) | ||||||
|     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) |  | ||||||
|         audio_play("/data/bong.ogg", NULL, false, 0.12f, 0.0f); |         audio_play("/data/bong.ogg", NULL, false, 0.12f, 0.0f); | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user