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