nuclear@20: #include nuclear@20: #include "opengl.h" nuclear@20: #include "cam.h" nuclear@20: #include "sanegl.h" nuclear@20: nuclear@20: #define DEG_TO_RAD(x) (M_PI * (x) / 180.0) nuclear@20: nuclear@20: typedef struct vec3 { nuclear@20: float x, y, z; nuclear@20: } vec3_t; nuclear@20: nuclear@20: /* viewing parameters */ nuclear@20: #define DEF_THETA 0 nuclear@20: #define DEF_PHI 0 nuclear@20: #define DEF_DIST 0 nuclear@20: #define DEF_X 0 nuclear@20: #define DEF_Y 0 nuclear@20: #define DEF_Z 0 nuclear@20: nuclear@20: static float cam_theta = DEF_THETA, cam_phi = DEF_PHI; nuclear@20: static float cam_dist = DEF_DIST; nuclear@20: static vec3_t cam_pos = {DEF_X, DEF_Y, DEF_Z}; nuclear@20: static float cam_speed = 1.0; nuclear@20: nuclear@20: /* projection parameters */ nuclear@20: #define DEF_VFOV 45.0 nuclear@20: #define DEF_ASPECT 1.3333333 nuclear@20: #define DEF_NEAR 1.0 nuclear@20: #define DEF_FAR 1000.0 nuclear@20: nuclear@20: static float vfov = DEF_VFOV; nuclear@20: static float aspect = DEF_ASPECT; nuclear@20: static float nearclip = DEF_NEAR, farclip = DEF_FAR; nuclear@20: nuclear@20: /* stereo parameters */ nuclear@20: #define DEF_EYE_SEP 0.1 nuclear@20: #define DEF_FOCUS_DIST 1.0 nuclear@20: nuclear@20: static float eye_sep = DEF_EYE_SEP; nuclear@20: static float focus_dist = DEF_FOCUS_DIST; nuclear@20: nuclear@20: nuclear@20: static float rot_speed = 0.5; nuclear@20: static float zoom_speed = 0.1; nuclear@20: nuclear@20: void cam_reset(void) nuclear@20: { nuclear@20: cam_reset_view(); nuclear@20: cam_reset_proj(); nuclear@20: cam_reset_stereo(); nuclear@20: } nuclear@20: nuclear@20: void cam_reset_view(void) nuclear@20: { nuclear@20: cam_theta = DEF_THETA; nuclear@20: cam_phi = DEF_PHI; nuclear@20: cam_dist = DEF_DIST; nuclear@20: cam_pos.x = DEF_X; nuclear@20: cam_pos.y = DEF_Y; nuclear@20: cam_pos.z = DEF_Z; nuclear@20: } nuclear@20: nuclear@20: void cam_reset_proj(void) nuclear@20: { nuclear@20: vfov = DEF_VFOV; nuclear@20: aspect = DEF_ASPECT; nuclear@20: nearclip = DEF_NEAR; nuclear@20: farclip = DEF_FAR; nuclear@20: } nuclear@20: nuclear@20: void cam_reset_stereo(void) nuclear@20: { nuclear@20: eye_sep = DEF_EYE_SEP; nuclear@20: focus_dist = DEF_FOCUS_DIST; nuclear@20: } nuclear@20: nuclear@20: void cam_pan(int dx, int dy) nuclear@20: { nuclear@20: float dxf = dx * cam_speed; nuclear@20: float dyf = dy * cam_speed; nuclear@20: float angle = -DEG_TO_RAD(cam_theta); nuclear@20: nuclear@20: cam_pos.x += cos(angle) * dxf + sin(angle) * dyf; nuclear@20: cam_pos.z += -sin(angle) * dxf + cos(angle) * dyf; nuclear@20: } nuclear@20: nuclear@20: void cam_height(int dh) nuclear@20: { nuclear@20: cam_pos.y += dh * cam_speed; nuclear@20: } nuclear@20: nuclear@20: void cam_rotate(int dx, int dy) nuclear@20: { nuclear@20: cam_theta += dx * rot_speed; nuclear@20: cam_phi += dy * rot_speed; nuclear@20: nuclear@20: if(cam_phi < -90) cam_phi = -90; nuclear@20: if(cam_phi > 90) cam_phi = 90; nuclear@20: } nuclear@20: nuclear@20: void cam_zoom(int dz) nuclear@20: { nuclear@20: cam_dist += dz * zoom_speed; nuclear@20: if(cam_dist < 0.001) { nuclear@20: cam_dist = 0.001; nuclear@20: } nuclear@20: } nuclear@20: nuclear@20: void cam_clip(float n, float f) nuclear@20: { nuclear@20: nearclip = n; nuclear@20: farclip = f; nuclear@20: } nuclear@20: nuclear@20: void cam_fov(float f) nuclear@20: { nuclear@20: vfov = f; nuclear@20: } nuclear@20: nuclear@20: void cam_aspect(float a) nuclear@20: { nuclear@20: aspect = a; nuclear@20: } nuclear@20: nuclear@20: void cam_separation(float s) nuclear@20: { nuclear@20: eye_sep = s; nuclear@20: } nuclear@20: nuclear@20: void cam_focus_dist(float d) nuclear@20: { nuclear@20: focus_dist = d; nuclear@20: nuclear@20: cam_separation(d / 30.0); nuclear@20: } nuclear@20: nuclear@20: void cam_view_matrix(void) nuclear@20: { nuclear@20: cam_stereo_view_matrix(CAM_CENTER); nuclear@20: } nuclear@20: nuclear@20: void cam_stereo_view_matrix(int eye) nuclear@20: { nuclear@20: static const float offs_sign[] = {0.0f, 0.5f, -0.5f}; /* center, left, right */ nuclear@20: float offs = eye_sep * offs_sign[eye]; nuclear@20: nuclear@20: gl_translatef(offs, 0, 0); nuclear@20: nuclear@20: gl_translatef(0, 0, -cam_dist); nuclear@20: gl_rotatef(cam_phi, 1, 0, 0); nuclear@20: gl_rotatef(cam_theta, 0, 1, 0); nuclear@20: gl_translatef(-cam_pos.x, -cam_pos.y, -cam_pos.z); nuclear@20: } nuclear@20: nuclear@20: void cam_proj_matrix(void) nuclear@20: { nuclear@20: cam_stereo_proj_matrix(CAM_CENTER); nuclear@20: } nuclear@20: nuclear@20: void cam_stereo_proj_matrix(int eye) nuclear@20: { nuclear@20: float vfov_rad = M_PI * vfov / 180.0; nuclear@20: float top = nearclip * tan(vfov_rad * 0.5); nuclear@20: float right = top * aspect; nuclear@20: nuclear@20: static const float offs_sign[] = {0.0f, 1.0, -1.0}; /* center, left, right */ nuclear@20: float frust_shift = offs_sign[eye] * (eye_sep * 0.5 * nearclip / focus_dist); nuclear@20: nuclear@20: gl_frustum(-right + frust_shift, right + frust_shift, -top, top, nearclip, farclip); nuclear@20: }