techkaczynski.dev / code

summaryrefslogtreecommitdiff
path: root/cam.c
diff options
context:
space:
mode:
authortech kaczynski <tk@techkaczynski.dev>2026-10-19 01:47:08 +1000
committertech kaczynski <tk@techkaczynski.dev>2026-10-19 01:47:08 +1000
commitedc50a43a0ab064472aa7fde90f14cf456d92076 (patch)
treec0281123898ddfa2d94683cbcd4cd85dd0d6ad6b /cam.c
parentcc4ba95edf2927eda63af1aeb79a503bc6fe6182 (diff)
lots of editor work. Improved editor camera controls.
Diffstat (limited to 'cam.c')
-rw-r--r--cam.c203
1 files changed, 193 insertions, 10 deletions
diff --git a/cam.c b/cam.c
index f14487c..4576f93 100644
--- a/cam.c
+++ b/cam.c
@@ -1,25 +1,157 @@
#include "cam.h"
+#include "reasings.h"
#include <rcamera.h>
+static void cam_ctrl_editor(void);
+static void cam_ctrl_orbit(void);
+
CameraInfo main_cam = {0};
void
cam_init(void) {
rlSetClipPlanes(0.3, 5000);
main_cam.cam = (Camera3D) {
- .position = { 0, 10, -10 },
+ .position = { 0, 10, 10 },
.target = { 0, 1, 0 },
.up = { 0, 1, 0},
.fovy = 70.0f,
.projection = CAMERA_PERSPECTIVE,
};
main_cam.update = false;
+ main_cam.allow_fly = true;
+ main_cam.state = CAM_MODE_EDIT_FLY;
+ main_cam.perspective_fov = main_cam.cam.fovy;
main_cam.mv_speed = 10;
main_cam.mv_scale = 1;
- main_cam.lk_speed = 0.2;
+ main_cam.lk_speed = 0.003f;
}
void
+cam_focus(Vec3 target, f32 distance, f32 view_height) {
+ Camera *cam = &main_cam.cam;
+ Vec3 backward = Vector3Normalize(
+ Vector3Subtract(cam->position, cam->target));
+
+ main_cam.transition.start_pos = cam->position;
+ main_cam.transition.start_target = cam->target;
+
+ main_cam.transition.end_target = target;
+ main_cam.transition.end_pos = Vector3Add(target,
+ Vector3Scale(backward, fmaxf(distance, 0.5f)));
+
+ main_cam.transition.start_fovy = cam->fovy;
+ main_cam.transition.end_fovy = cam->fovy;
+
+ if (cam->projection == CAMERA_ORTHOGRAPHIC) {
+ main_cam.transition.end_fovy = fmaxf(view_height, 0.1f);
+ }
+
+ main_cam.transition.elapsed = 0;
+ main_cam.transition.active = true;
+ main_cam.state = CAM_MODE_EDIT_ORBIT;
+}
+
+void
+cam_update(void) {
+ if (main_cam.input) {
+ if (!main_cam.update && !main_cam.transition.active &&
+ IsKeyPressed(KEY_P)) {
+ Camera *cam = &main_cam.cam;
+ 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;
+ main_cam.state = CAM_MODE_EDIT_ORBIT;
+ } else {
+ Vec3 backward = Vector3Normalize(
+ Vector3Subtract(cam->position,
+ cam->target));
+
+ distance = cam->fovy / (2.0f *
+ tanf(main_cam.perspective_fov *
+ DEG2RAD * 0.5f));
+
+ cam->position = Vector3Add(
+ cam->target,
+ Vector3Scale(backward, distance)
+ );
+
+ cam->fovy = main_cam.perspective_fov;
+ cam->projection = CAMERA_PERSPECTIVE;
+ }
+ }
+
+ 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;
+ }
+
+ bool navigate = main_cam.update ||
+ (main_cam.state == CAM_MODE_EDIT_ORBIT &&
+ GetMouseWheelMove() != 0);
+
+ if (navigate && !main_cam.transition.active) {
+ switch (main_cam.state) {
+ case CAM_MODE_EDIT_FLY:
+ cam_ctrl_editor();
+ break;
+
+ case CAM_MODE_EDIT_ORBIT:
+ cam_ctrl_orbit();
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+
+ if (!main_cam.transition.active) {
+ return;
+ }
+
+ const f32 duration = 0.25f;
+ main_cam.transition.elapsed = fminf(
+ main_cam.transition.elapsed + GetFrameTime(), duration);
+
+ f32 t = EaseSineInOut(
+ main_cam.transition.elapsed, 0.0f, 1.0f, duration);
+
+ main_cam.cam.position = Vector3Lerp(
+ main_cam.transition.start_pos,
+ main_cam.transition.end_pos, t);
+
+ main_cam.cam.target = Vector3Lerp(
+ main_cam.transition.start_target,
+ main_cam.transition.end_target, t);
+
+ main_cam.cam.fovy = Lerp(
+ main_cam.transition.start_fovy,
+ main_cam.transition.end_fovy, t);
+
+ 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.fovy = main_cam.transition.end_fovy;
+ main_cam.transition.active = false;
+ }
+}
+
+static void
cam_ctrl_editor(void) {
if (!main_cam.update) {
return;
@@ -61,14 +193,14 @@ cam_ctrl_editor(void) {
// makes it so you can stop faster than you can speed up
f32 ms_amount = GetMouseWheelMove() < 0 ?
- GetMouseWheelMove() * 1.5 :
- GetMouseWheelMove() * 0.75;
+ GetMouseWheelMove() * 1.0 :
+ GetMouseWheelMove() * 0.5;
main_cam.mv_scale += ms_amount;
- main_cam.mv_scale = CLAMP(main_cam.mv_scale, 0.1, 50);
+ main_cam.mv_scale = CLAMP(main_cam.mv_scale, 0.05, 80);
mv_speed *= main_cam.mv_scale;
- mv_speed = CLAMP(mv_speed, 2, 1000);
+ mv_speed = CLAMP(mv_speed, 1, 1000);
CameraMoveForward(&main_cam.cam,
input_dir.z * mv_speed * GetFrameTime(),
@@ -80,9 +212,60 @@ cam_ctrl_editor(void) {
CameraMoveUp(&main_cam.cam, input_dir.y * mv_speed * GetFrameTime());
- CameraYaw(&main_cam.cam,
- -GetMouseDelta().x * lk_speed * GetFrameTime(), 0);
+ 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
+cam_ctrl_orbit(void) {
+ Camera *cam = &main_cam.cam;
+ f32 wheel = GetMouseWheelMove();
+ f32 view_height;
+
+ if (cam->projection == CAMERA_ORTHOGRAPHIC) {
+ if (wheel != 0) {
+ cam->fovy = Clamp(
+ cam->fovy * powf(0.85f, wheel), 0.1f, 2000.0f);
+ }
- CameraPitch(&main_cam.cam,
- -GetMouseDelta().y * lk_speed * GetFrameTime(), 1, 0, 0);
+ view_height = cam->fovy;
+ } else {
+ f32 distance = Vector3Distance(cam->position, cam->target);
+
+ if (wheel != 0) {
+ f32 zoom = Clamp(
+ distance * powf(0.85f, wheel), 0.5f, 1000.0f);
+ CameraMoveToTarget(cam, zoom - distance);
+ distance = zoom;
+ }
+
+ view_height = 2.0f * distance *
+ tanf(cam->fovy * DEG2RAD * 0.5f);
+ }
+
+ if (!main_cam.update) {
+ return;
+ }
+
+ Vec2 delta = GetMouseDelta();
+
+ if (IsMouseButtonDown(MOUSE_MIDDLE_BUTTON)) {
+ Vec3 forward = GetCameraForward(cam);
+ Vec3 right = GetCameraRight(cam);
+ Vec3 up = Vector3Normalize(
+ Vector3CrossProduct(right, forward));
+
+ f32 scale = view_height / GetScreenHeight();
+ Vec3 offset = Vector3Add(
+ Vector3Scale(right, -delta.x * scale),
+ Vector3Scale(up, delta.y * scale));
+
+ 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);
+ }
}