From bd1268267e1b0cbf6253c992bce0e5224da7fa01 Mon Sep 17 00:00:00 2001 From: tech kaczynski Date: Mon, 19 Oct 2026 04:05:26 +1000 Subject: updated editor move tool and related gizmos. --- cam.c | 198 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 175 insertions(+), 23 deletions(-) (limited to 'cam.c') diff --git a/cam.c b/cam.c index 4576f93..6827709 100644 --- a/cam.c +++ b/cam.c @@ -21,6 +21,7 @@ cam_init(void) { main_cam.allow_fly = true; main_cam.state = CAM_MODE_EDIT_FLY; main_cam.perspective_fov = main_cam.cam.fovy; + main_cam.view_rotation = QuaternionIdentity(); main_cam.mv_speed = 10; main_cam.mv_scale = 1; main_cam.lk_speed = 0.003f; @@ -32,6 +33,15 @@ cam_focus(Vec3 target, f32 distance, f32 view_height) { Vec3 backward = Vector3Normalize( Vector3Subtract(cam->position, cam->target)); + Quaternion rotation = QuaternionNormalize( + QuaternionFromMatrix(MatrixTranspose(MatrixLookAt( + Vector3Zero(), + Vector3Negate(backward), + cam->up)))); + + main_cam.transition.start_rot = rotation; + main_cam.transition.end_rot = rotation; + main_cam.transition.start_pos = cam->position; main_cam.transition.start_target = cam->target; @@ -51,11 +61,91 @@ cam_focus(Vec3 target, f32 distance, f32 view_height) { main_cam.state = CAM_MODE_EDIT_ORBIT; } +static void +cam_axis_view(int axis, bool negative) { + Camera *cam = &main_cam.cam; + f32 side = negative ? -1.0f : 1.0f; + + Vec3 backward = {0}; + Vec3 up = {0, 1, 0}; + + switch (axis) { + case 0: + backward.x = side; + break; + + case 1: + backward.y = side; + up = (Vec3){0, 0, -side}; + break; + + case 2: + backward.z = side; + break; + } + + if (main_cam.local_space) { + backward = Vector3RotateByQuaternion( + backward, main_cam.view_rotation); + up = Vector3RotateByQuaternion( + up, main_cam.view_rotation); + } + + f32 distance = Vector3Distance(cam->position, cam->target); + + if (cam->projection == CAMERA_PERSPECTIVE) { + main_cam.perspective_fov = cam->fovy; + cam->fovy = 2.0f * distance * + tanf(main_cam.perspective_fov * DEG2RAD * 0.5f); + cam->projection = CAMERA_ORTHOGRAPHIC; + } + + cam_focus(cam->target, distance, cam->fovy); + + main_cam.transition.end_pos = Vector3Add( + cam->target, Vector3Scale(backward, distance)); + + Matrix view = MatrixLookAt( + Vector3Zero(), Vector3Negate(backward), up); + + main_cam.transition.end_rot = QuaternionNormalize( + QuaternionFromMatrix(MatrixTranspose(view))); + + main_cam.axis_view = true; +} + void cam_update(void) { if (main_cam.input) { - if (!main_cam.update && !main_cam.transition.active && - IsKeyPressed(KEY_P)) { + bool fly = main_cam.update && + main_cam.allow_fly && + IsMouseButtonDown(MOUSE_BUTTON_RIGHT) && + (IsKeyDown(KEY_W) || IsKeyDown(KEY_A) || + IsKeyDown(KEY_S) || IsKeyDown(KEY_D) || + IsKeyDown(KEY_Q) || IsKeyDown(KEY_E)); + + if (fly) { + main_cam.transition.active = false; + main_cam.state = CAM_MODE_EDIT_FLY; + } + + Vec2 mouse = GetMouseDelta(); + bool rotate = main_cam.update && + IsMouseButtonDown(MOUSE_BUTTON_RIGHT) && + !IsMouseButtonDown(MOUSE_BUTTON_MIDDLE) && + (mouse.x != 0 || mouse.y != 0); + + bool toggle = !main_cam.update && + !main_cam.transition.active && + IsKeyPressed(KEY_P); + + bool leave_axis = main_cam.axis_view && + !main_cam.transition.active && + (fly || rotate); + + if (toggle || leave_axis) { + main_cam.axis_view = false; + Camera *cam = &main_cam.cam; f32 distance = Vector3Distance( cam->position, cam->target); @@ -75,8 +165,8 @@ cam_update(void) { cam->target)); distance = cam->fovy / (2.0f * - tanf(main_cam.perspective_fov * - DEG2RAD * 0.5f)); + tanf(main_cam.perspective_fov * + DEG2RAD * 0.5f)); cam->position = Vector3Add( cam->target, @@ -88,16 +178,21 @@ cam_update(void) { } } - bool fly = main_cam.update && - main_cam.allow_fly && - IsMouseButtonDown(MOUSE_BUTTON_RIGHT) && - (IsKeyDown(KEY_W) || IsKeyDown(KEY_A) || - IsKeyDown(KEY_S) || IsKeyDown(KEY_D) || - IsKeyDown(KEY_Q) || IsKeyDown(KEY_E)); + if (!main_cam.update && !main_cam.transition.active && + !IsKeyDown(KEY_LEFT_CONTROL)) { + if (IsKeyPressed(KEY_L)) { + main_cam.local_space = !main_cam.local_space; + } - if (fly) { - main_cam.transition.active = false; - main_cam.state = CAM_MODE_EDIT_FLY; + bool negative = IsKeyDown(KEY_LEFT_SHIFT); + + if (IsKeyPressed(KEY_X)) { + cam_axis_view(0, negative); + } else if (IsKeyPressed(KEY_Y)) { + cam_axis_view(1, negative); + } else if (IsKeyPressed(KEY_Z)) { + cam_axis_view(2, negative); + } } bool navigate = main_cam.update || @@ -131,14 +226,29 @@ cam_update(void) { f32 t = EaseSineInOut( main_cam.transition.elapsed, 0.0f, 1.0f, duration); - main_cam.cam.position = Vector3Lerp( + Quaternion rotation = QuaternionSlerp( + main_cam.transition.start_rot, + main_cam.transition.end_rot, t); + + f32 start_distance = Vector3Distance( main_cam.transition.start_pos, - main_cam.transition.end_pos, t); + main_cam.transition.start_target); + f32 end_distance = Vector3Distance( + main_cam.transition.end_pos, + main_cam.transition.end_target); + f32 distance = Lerp(start_distance, end_distance, t); main_cam.cam.target = Vector3Lerp( main_cam.transition.start_target, main_cam.transition.end_target, t); + Vec3 backward = Vector3RotateByQuaternion( + (Vec3){0, 0, 1}, rotation); + main_cam.cam.position = Vector3Add( + main_cam.cam.target, Vector3Scale(backward, distance)); + main_cam.cam.up = Vector3RotateByQuaternion( + (Vec3){0, 1, 0}, rotation); + main_cam.cam.fovy = Lerp( main_cam.transition.start_fovy, main_cam.transition.end_fovy, t); @@ -146,20 +256,68 @@ cam_update(void) { if (main_cam.transition.elapsed >= duration) { main_cam.cam.position = main_cam.transition.end_pos; main_cam.cam.target = main_cam.transition.end_target; + main_cam.cam.up = Vector3RotateByQuaternion( + (Vec3){0, 1, 0}, main_cam.transition.end_rot); main_cam.cam.fovy = main_cam.transition.end_fovy; main_cam.transition.active = false; } } +static void +cam_rotate(bool orbit) { + Camera *cam = &main_cam.cam; + Vec2 delta = GetMouseDelta(); + + if (orbit && delta.x == 0 && delta.y == 0) { + return; + } + + Vec3 offset = Vector3Subtract(cam->position, cam->target); + f32 distance = Vector3Length(offset); + Vec3 backward = Vector3Scale(offset, 1.0f / distance); + + f32 yaw = atan2f(backward.x, backward.z); + f32 pitch = asinf(Clamp(backward.y, -1.0f, 1.0f)); + + /* At a pole, use screen-up to recover the heading. */ + if (backward.x * backward.x + + backward.z * backward.z < 0.000001f) { + f32 side = backward.y > 0 ? -1.0f : 1.0f; + yaw = atan2f(cam->up.x * side, cam->up.z * side); + } + + yaw -= delta.x * main_cam.lk_speed; + pitch += delta.y * main_cam.lk_speed; + pitch = Clamp(pitch, -PI * 0.5f + 0.001f, + PI * 0.5f - 0.001f); + + backward = (Vec3){ + sinf(yaw) * cosf(pitch), + sinf(pitch), + cosf(yaw) * cosf(pitch), + }; + + offset = Vector3Scale(backward, distance); + + if (orbit) { + cam->position = Vector3Add(cam->target, offset); + } else { + cam->target = Vector3Subtract(cam->position, offset); + } + + cam->up = (Vec3){0, 1, 0}; +} + static void cam_ctrl_editor(void) { if (!main_cam.update) { return; } + cam_rotate(false); + Vec3 input_dir = {0}; f32 mv_speed = main_cam.mv_speed; - f32 lk_speed = main_cam.lk_speed; if (IsKeyDown(KEY_W)) { input_dir.z += 1; @@ -211,10 +369,6 @@ cam_ctrl_editor(void) { false); CameraMoveUp(&main_cam.cam, input_dir.y * mv_speed * GetFrameTime()); - - Vec2 delta = GetMouseDelta(); - CameraYaw(&main_cam.cam, -delta.x * lk_speed, false); - CameraPitch(&main_cam.cam, -delta.y * lk_speed, true, false, false); } static void @@ -264,8 +418,6 @@ cam_ctrl_orbit(void) { cam->position = Vector3Add(cam->position, offset); cam->target = Vector3Add(cam->target, offset); } else { - CameraYaw(cam, -delta.x * main_cam.lk_speed, true); - CameraPitch(cam, -delta.y * main_cam.lk_speed, - true, true, false); + cam_rotate(true); } } -- cgit v1.2.3