AnimTestbed/src/camera.h

134 lines
4.1 KiB
C
Raw Normal View History

2021-11-11 21:22:24 +01:00
#pragma once
/*
Quick'n'dirty Maya-style camera. Include after HandmadeMath.h
and sokol_app.h
*/
#include <string.h>
#include <math.h>
#define CAMERA_DEFAULT_MIN_DIST (2.0f)
#define CAMERA_DEFAULT_MAX_DIST (30.0f)
#define CAMERA_DEFAULT_MIN_LAT (-85.0f)
#define CAMERA_DEFAULT_MAX_LAT (85.0f)
#define CAMERA_DEFAULT_DIST (5.0f)
#define CAMERA_DEFAULT_ASPECT (60.0f)
#define CAMERA_DEFAULT_NEARZ (0.01f)
#define CAMERA_DEFAULT_FARZ (100.0f)
typedef struct {
float min_dist;
float max_dist;
float min_lat;
float max_lat;
float distance;
float latitude;
float longitude;
float aspect;
float nearz;
float farz;
hmm_vec3 center;
} camera_desc_t;
typedef struct {
float min_dist;
float max_dist;
float min_lat;
float max_lat;
float distance;
float latitude;
float longitude;
float aspect;
float nearz;
float farz;
hmm_vec3 center;
hmm_vec3 eye_pos;
hmm_mat4 view;
hmm_mat4 proj;
hmm_mat4 view_proj;
} camera_t;
static float _cam_def(float val, float def) {
return ((val == 0.0f) ? def:val);
}
/* initialize to default parameters */
static void cam_init(camera_t* cam, const camera_desc_t* desc) {
assert(cam && desc);
memset(cam, 0, sizeof(camera_t));
cam->min_dist = _cam_def(desc->min_dist, CAMERA_DEFAULT_MIN_DIST);
cam->max_dist = _cam_def(desc->max_dist, CAMERA_DEFAULT_MAX_DIST);
cam->min_lat = _cam_def(desc->min_lat, CAMERA_DEFAULT_MIN_LAT);
cam->max_lat = _cam_def(desc->max_lat, CAMERA_DEFAULT_MAX_LAT);
cam->distance = _cam_def(desc->distance, CAMERA_DEFAULT_DIST);
cam->center = desc->center;
cam->latitude = desc->latitude;
cam->longitude = desc->longitude;
cam->aspect = _cam_def(desc->aspect, CAMERA_DEFAULT_ASPECT);
cam->nearz = _cam_def(desc->nearz, CAMERA_DEFAULT_NEARZ);
cam->farz = _cam_def(desc->farz, CAMERA_DEFAULT_FARZ);
}
/* feed mouse movement */
static void cam_orbit(camera_t* cam, float dx, float dy) {
assert(cam);
cam->longitude -= dx;
if (cam->longitude < 0.0f) {
cam->longitude += 360.0f;
}
if (cam->longitude > 360.0f) {
cam->longitude -= 360.0f;
}
cam->latitude = HMM_Clamp(cam->min_lat, cam->latitude + dy, cam->max_lat);
}
/* feed zoom (mouse wheel) input */
static void cam_zoom(camera_t* cam, float d) {
assert(cam);
cam->distance = HMM_Clamp(cam->min_dist, cam->distance + d, cam->max_dist);
}
static hmm_vec3 _cam_euclidean(float latitude, float longitude) {
const float lat = HMM_ToRadians(latitude);
const float lng = HMM_ToRadians(longitude);
return HMM_Vec3(cosf(lat) * sinf(lng), sinf(lat), cosf(lat) * cosf(lng));
}
/* update the view, proj and view_proj matrix */
static void cam_update(camera_t* cam, int fb_width, int fb_height) {
assert(cam);
assert((fb_width > 0) && (fb_height > 0));
const float w = (float) fb_width;
const float h = (float) fb_height;
cam->eye_pos = HMM_AddVec3(cam->center, HMM_MultiplyVec3f(_cam_euclidean(cam->latitude, cam->longitude), cam->distance));
cam->view = HMM_LookAt(cam->eye_pos, cam->center, HMM_Vec3(0.0f, 1.0f, 0.0f));
cam->proj = HMM_Perspective(cam->aspect, w/h, cam->nearz, cam->farz);
cam->view_proj = HMM_MultiplyMat4(cam->proj, cam->view);
}
/* handle sokol-app input events */
//static void cam_handle_event(camera_t* cam, const sapp_event* ev) {
// assert(cam);
// switch (ev->type) {
// case SAPP_EVENTTYPE_MOUSE_DOWN:
// if (ev->mouse_button == SAPP_MOUSEBUTTON_LEFT) {
// sapp_lock_mouse(true);
// }
// break;
// case SAPP_EVENTTYPE_MOUSE_UP:
// if (ev->mouse_button == SAPP_MOUSEBUTTON_LEFT) {
// sapp_lock_mouse(false);
// }
// break;
// case SAPP_EVENTTYPE_MOUSE_SCROLL:
// cam_zoom(cam, ev->scroll_y * 0.5f);
// break;
// case SAPP_EVENTTYPE_MOUSE_MOVE:
// if (sapp_mouse_locked()) {
// cam_orbit(cam, ev->mouse_dx * 0.25f, ev->mouse_dy * 0.25f);
// }
// break;
// default:
// break;
// }
//}