1#include "client/camera.h"
2#include "mgmath.h"
3
4#define MAX_PITCH (MG_AngleDeg(89.0f)) /* < 90 so no div by 0s */
5
6void camera_init(MGCamera* cam, MGVec3 pos)
7{
8 /* TODO: maybe some immediate mode ui could be nice? */
9 /* IMGUI imgui Immediate */
10 cam->pos = pos;
11 cam->yaw = 0.0f;
12 cam->pitch = 0.0f;
13 cam->fov = MG_AngleDeg(70.0f);
14 cam->near = 0.1f;
15 cam->far = 100.0f;
16}
17
18void camera_move(MGCamera* cam, MGVec3 offset)
19{
20 MGVec3 forward = camera_get_forward(cam);
21 MGVec3 right = camera_get_right(cam);
22 MGVec3 movement = MG_V3(0.0f, 0.0f, 0.0f);
23
24 /* ignore pitch so we don't go to where we look */
25 forward.y = 0.0f;
26 forward = MG_NormV3(forward);
27
28 movement = MG_AddV3(movement, MG_MulV3F(forward, offset.z));
29 movement = MG_AddV3(movement, MG_MulV3F(right, offset.x));
30
31 movement.y += offset.y;
32 cam->pos = MG_AddV3(cam->pos, movement);
33}
34
35void camera_rotate(MGCamera* cam, float dyaw, float dpitch)
36{
37 cam->yaw += dyaw;
38 cam->pitch += dpitch;
39
40 if (cam->pitch > MAX_PITCH)
41 cam->pitch = MAX_PITCH;
42
43 if (cam->pitch < -MAX_PITCH)
44 cam->pitch = -MAX_PITCH;
45}
46
47MGVec3 camera_get_forward(const MGCamera* cam)
48{
49 MGVec3 forward;
50 float pcos = MG_CosF(cam->pitch);
51
52 forward.x = pcos * MG_SinF(cam->yaw);
53 forward.y = MG_SinF(cam->pitch);
54 forward.z = -pcos * MG_CosF(cam->yaw);
55 return MG_NormV3(forward);
56}
57
58MGVec3 camera_get_right(const MGCamera* cam)
59{
60 return MG_NormV3(MG_Cross(camera_get_forward(cam), MG_V3(0.0f, 1.0f, 0.0f)));
61}
62
63MGMat4 camera_get_view(const MGCamera* cam)
64{
65 MGVec3 target = MG_AddV3(cam->pos, camera_get_forward(cam));
66 return MG_LookAt_RH(cam->pos, target, MG_V3(0.0f, 1.0f, 0.0f));
67}
68
69MGMat4 camera_get_proj(const MGCamera* cam, float aspect)
70{
71 return MG_Perspective_RH_NO(cam->fov, aspect, cam->near, cam->far);
72}
73