nuclear@0: #include nuclear@0: #include "cam.h" nuclear@0: nuclear@0: #if defined(__APPLE__) && defined(__MACH__) nuclear@0: #include nuclear@0: #else nuclear@0: #include nuclear@0: #endif nuclear@0: nuclear@0: #define DR (M_PI / 180.0) nuclear@0: #define DEG_TO_RAD(x) ((x) * DR) nuclear@0: nuclear@0: typedef struct vec3 { nuclear@0: float x, y, z; nuclear@0: } vec3_t; nuclear@0: nuclear@0: /* viewing parameters */ nuclear@0: #define DEF_THETA 0 nuclear@0: #define DEF_PHI 0 nuclear@0: #define DEF_DIST 0 nuclear@0: #define DEF_X 0 nuclear@0: #define DEF_Y 0 nuclear@0: #define DEF_Z 0 nuclear@0: nuclear@0: static float cam_theta = DEF_THETA, cam_phi = DEF_PHI; nuclear@0: static float cam_dist = DEF_DIST; nuclear@0: static vec3_t cam_pos = {DEF_X, DEF_Y, DEF_Z}; nuclear@0: nuclear@0: /* projection parameters */ nuclear@0: #define DEF_VFOV 45.0 nuclear@0: #define DEF_ASPECT 1.3333333 nuclear@0: #define DEF_NEAR 1.0 nuclear@0: #define DEF_FAR 1000.0 nuclear@0: nuclear@0: static float vfov = DEF_VFOV; nuclear@0: static float aspect = DEF_ASPECT; nuclear@0: static float nearclip = DEF_NEAR, farclip = DEF_FAR; nuclear@0: nuclear@0: /* stereo parameters */ nuclear@0: #define DEF_EYE_SEP 0.1 nuclear@0: #define DEF_FOCUS_DIST 1.0 nuclear@0: nuclear@0: static float eye_sep = DEF_EYE_SEP; nuclear@0: static float focus_dist = DEF_FOCUS_DIST; nuclear@0: nuclear@0: static float pan_speed = 0.001; nuclear@0: static float rot_speed = 0.5; nuclear@0: static float zoom_speed = 0.1; nuclear@0: nuclear@0: static float vmin_deg = -90.0, vmax_deg = 90.0; nuclear@0: nuclear@0: void cam_reset(void) nuclear@0: { nuclear@0: cam_reset_view(); nuclear@0: cam_reset_proj(); nuclear@0: cam_reset_stereo(); nuclear@0: } nuclear@0: nuclear@0: void cam_reset_view(void) nuclear@0: { nuclear@0: cam_theta = DEF_THETA; nuclear@0: cam_phi = DEF_PHI; nuclear@0: cam_dist = DEF_DIST; nuclear@0: cam_pos.x = DEF_X; nuclear@0: cam_pos.y = DEF_Y; nuclear@0: cam_pos.z = DEF_Z; nuclear@0: } nuclear@0: nuclear@0: void cam_reset_proj(void) nuclear@0: { nuclear@0: vfov = DEF_VFOV; nuclear@0: aspect = DEF_ASPECT; nuclear@0: nearclip = DEF_NEAR; nuclear@0: farclip = DEF_FAR; nuclear@0: } nuclear@0: nuclear@0: void cam_reset_stereo(void) nuclear@0: { nuclear@0: eye_sep = DEF_EYE_SEP; nuclear@0: focus_dist = DEF_FOCUS_DIST; nuclear@0: } nuclear@0: nuclear@0: void cam_set_vrange(float min_deg, float max_deg) nuclear@0: { nuclear@0: vmin_deg = min_deg; nuclear@0: vmax_deg = max_deg; nuclear@0: } nuclear@0: nuclear@0: void cam_move(float x, float y, float z) nuclear@0: { nuclear@0: cam_pos.x += x; nuclear@0: cam_pos.y += y; nuclear@0: cam_pos.z += z; nuclear@0: } nuclear@0: nuclear@0: void cam_rotate(float theta, float phi) nuclear@0: { nuclear@0: cam_phi += phi; nuclear@0: cam_theta += theta; nuclear@0: } nuclear@0: nuclear@0: void cam_dolly(float dist) nuclear@0: { nuclear@0: cam_dist += dist; nuclear@0: } nuclear@0: nuclear@0: void cam_inp_pan_speed(float speed) nuclear@0: { nuclear@0: pan_speed = speed; nuclear@0: } nuclear@0: nuclear@0: void cam_inp_rotate_speed(float speed) nuclear@0: { nuclear@0: rot_speed = speed; nuclear@0: } nuclear@0: nuclear@0: void cam_inp_zoom_speed(float speed) nuclear@0: { nuclear@0: zoom_speed = speed; nuclear@0: } nuclear@0: nuclear@0: nuclear@0: void cam_inp_pan(int dx, int dy) nuclear@0: { nuclear@0: float dxf = dx * pan_speed; nuclear@0: float dyf = dy * pan_speed; nuclear@0: float angle = -DEG_TO_RAD(cam_theta); nuclear@0: nuclear@0: cam_pos.x += cos(angle) * dxf + sin(angle) * dyf; nuclear@0: cam_pos.z += -sin(angle) * dxf + cos(angle) * dyf; nuclear@0: } nuclear@0: nuclear@0: void cam_inp_height(int dh) nuclear@0: { nuclear@0: cam_pos.y += dh * pan_speed; nuclear@0: } nuclear@0: nuclear@0: void cam_inp_rotate(int dx, int dy) nuclear@0: { nuclear@0: cam_theta += dx * rot_speed; nuclear@0: cam_phi += dy * rot_speed; nuclear@0: nuclear@0: if(cam_phi < vmin_deg) cam_phi = vmin_deg; nuclear@0: if(cam_phi > vmax_deg) cam_phi = vmax_deg; nuclear@0: } nuclear@0: nuclear@0: void cam_inp_zoom(int dz) nuclear@0: { nuclear@0: cam_dist += dz * zoom_speed; nuclear@0: if(cam_dist < 0.001) { nuclear@0: cam_dist = 0.001; nuclear@0: } nuclear@0: } nuclear@0: nuclear@0: void cam_clip(float n, float f) nuclear@0: { nuclear@0: nearclip = n; nuclear@0: farclip = f; nuclear@0: } nuclear@0: nuclear@0: void cam_fov(float f) nuclear@0: { nuclear@0: vfov = f; nuclear@0: } nuclear@0: nuclear@0: void cam_aspect(float a) nuclear@0: { nuclear@0: aspect = a; nuclear@0: } nuclear@0: nuclear@0: void cam_separation(float s) nuclear@0: { nuclear@0: eye_sep = s; nuclear@0: } nuclear@0: nuclear@0: void cam_focus_dist(float d) nuclear@0: { nuclear@0: focus_dist = d; nuclear@0: nuclear@0: cam_separation(d / 30.0); nuclear@0: } nuclear@0: nuclear@0: void cam_view_matrix(void) nuclear@0: { nuclear@0: cam_stereo_view_matrix(CAM_CENTER); nuclear@0: } nuclear@0: nuclear@0: void cam_stereo_view_matrix(int eye) nuclear@0: { nuclear@0: static const float offs_sign[] = {0.0f, 0.5f, -0.5f}; /* center, left, right */ nuclear@0: float offs = eye_sep * offs_sign[eye]; nuclear@0: nuclear@0: glTranslatef(offs, 0, 0); nuclear@0: nuclear@0: glTranslatef(0, 0, -cam_dist); nuclear@0: glRotatef(cam_phi, 1, 0, 0); nuclear@0: glRotatef(cam_theta, 0, 1, 0); nuclear@0: glTranslatef(-cam_pos.x, -cam_pos.y, -cam_pos.z); nuclear@0: } nuclear@0: nuclear@0: void cam_proj_matrix(void) nuclear@0: { nuclear@0: cam_stereo_proj_matrix(CAM_CENTER); nuclear@0: } nuclear@0: nuclear@0: void cam_stereo_proj_matrix(int eye) nuclear@0: { nuclear@0: float vfov_rad = M_PI * vfov / 180.0; nuclear@0: float top = nearclip * tan(vfov_rad * 0.5); nuclear@0: float right = top * aspect; nuclear@0: nuclear@0: static const float offs_sign[] = {0.0f, 1.0, -1.0}; /* center, left, right */ nuclear@0: float frust_shift = offs_sign[eye] * (eye_sep * 0.5 * nearclip / focus_dist); nuclear@0: nuclear@0: glFrustum(-right + frust_shift, right + frust_shift, -top, top, nearclip, farclip); nuclear@0: }