nuclear@2: /* nuclear@2: Stereoscopic tunnel for iOS. nuclear@2: Copyright (C) 2011 John Tsiombikas nuclear@2: nuclear@2: This program is free software: you can redistribute it and/or modify nuclear@2: it under the terms of the GNU General Public License as published by nuclear@2: the Free Software Foundation, either version 3 of the License, or nuclear@2: (at your option) any later version. nuclear@2: nuclear@2: This program is distributed in the hope that it will be useful, nuclear@2: but WITHOUT ANY WARRANTY; without even the implied warranty of nuclear@2: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the nuclear@2: GNU General Public License for more details. nuclear@2: nuclear@2: You should have received a copy of the GNU General Public License nuclear@2: along with this program. If not, see . nuclear@2: */ nuclear@2: nuclear@2: #include nuclear@2: #include "opengl.h" nuclear@2: #include "cam.h" nuclear@2: #include "sanegl.h" nuclear@2: nuclear@2: #define DEG_TO_RAD(x) (M_PI * (x) / 180.0) nuclear@2: nuclear@2: typedef struct vec3 { nuclear@2: float x, y, z; nuclear@2: } vec3_t; nuclear@2: nuclear@2: /* viewing parameters */ nuclear@2: #define DEF_THETA 0 nuclear@2: #define DEF_PHI 0 nuclear@2: #define DEF_DIST 0 nuclear@2: #define DEF_X 0 nuclear@2: #define DEF_Y 0 nuclear@2: #define DEF_Z 0 nuclear@2: nuclear@2: static float cam_theta = DEF_THETA, cam_phi = DEF_PHI; nuclear@2: static float cam_dist = DEF_DIST; nuclear@2: static vec3_t cam_pos = {DEF_X, DEF_Y, DEF_Z}; nuclear@2: static float cam_speed = 1.0; nuclear@2: nuclear@2: /* projection parameters */ nuclear@2: #define DEF_VFOV 45.0 nuclear@2: #define DEF_ASPECT 1.3333333 nuclear@2: #define DEF_NEAR 1.0 nuclear@2: #define DEF_FAR 1000.0 nuclear@2: nuclear@2: static float vfov = DEF_VFOV; nuclear@2: static float aspect = DEF_ASPECT; nuclear@2: static float nearclip = DEF_NEAR, farclip = DEF_FAR; nuclear@2: nuclear@2: /* stereo parameters */ nuclear@2: #define DEF_EYE_SEP 0.1 nuclear@2: #define DEF_FOCUS_DIST 1.0 nuclear@2: nuclear@2: static float eye_sep = DEF_EYE_SEP; nuclear@2: static float focus_dist = DEF_FOCUS_DIST; nuclear@2: nuclear@2: nuclear@2: static float rot_speed = 0.5; nuclear@2: static float zoom_speed = 0.1; nuclear@2: nuclear@2: void cam_reset(void) nuclear@2: { nuclear@2: cam_reset_view(); nuclear@2: cam_reset_proj(); nuclear@2: cam_reset_stereo(); nuclear@2: } nuclear@2: nuclear@2: void cam_reset_view(void) nuclear@2: { nuclear@2: cam_theta = DEF_THETA; nuclear@2: cam_phi = DEF_PHI; nuclear@2: cam_dist = DEF_DIST; nuclear@2: cam_pos.x = DEF_X; nuclear@2: cam_pos.y = DEF_Y; nuclear@2: cam_pos.z = DEF_Z; nuclear@2: } nuclear@2: nuclear@2: void cam_reset_proj(void) nuclear@2: { nuclear@2: vfov = DEF_VFOV; nuclear@2: aspect = DEF_ASPECT; nuclear@2: nearclip = DEF_NEAR; nuclear@2: farclip = DEF_FAR; nuclear@2: } nuclear@2: nuclear@2: void cam_reset_stereo(void) nuclear@2: { nuclear@2: eye_sep = DEF_EYE_SEP; nuclear@2: focus_dist = DEF_FOCUS_DIST; nuclear@2: } nuclear@2: nuclear@2: void cam_pan(int dx, int dy) nuclear@2: { nuclear@2: float dxf = dx * cam_speed; nuclear@2: float dyf = dy * cam_speed; nuclear@2: float angle = -DEG_TO_RAD(cam_theta); nuclear@2: nuclear@2: cam_pos.x += cos(angle) * dxf + sin(angle) * dyf; nuclear@2: cam_pos.z += -sin(angle) * dxf + cos(angle) * dyf; nuclear@2: } nuclear@2: nuclear@2: void cam_height(int dh) nuclear@2: { nuclear@2: cam_pos.y += dh * cam_speed; nuclear@2: } nuclear@2: nuclear@2: void cam_rotate(int dx, int dy) nuclear@2: { nuclear@2: cam_theta += dx * rot_speed; nuclear@2: cam_phi += dy * rot_speed; nuclear@2: nuclear@2: if(cam_phi < -90) cam_phi = -90; nuclear@2: if(cam_phi > 90) cam_phi = 90; nuclear@2: } nuclear@2: nuclear@2: void cam_zoom(int dz) nuclear@2: { nuclear@2: cam_dist += dz * zoom_speed; nuclear@2: if(cam_dist < 0.001) { nuclear@2: cam_dist = 0.001; nuclear@2: } nuclear@2: } nuclear@2: nuclear@2: void cam_clip(float n, float f) nuclear@2: { nuclear@2: nearclip = n; nuclear@2: farclip = f; nuclear@2: } nuclear@2: nuclear@2: void cam_fov(float f) nuclear@2: { nuclear@2: vfov = f; nuclear@2: } nuclear@2: nuclear@2: void cam_aspect(float a) nuclear@2: { nuclear@2: aspect = a; nuclear@2: } nuclear@2: nuclear@2: void cam_separation(float s) nuclear@2: { nuclear@2: eye_sep = s; nuclear@2: } nuclear@2: nuclear@2: void cam_focus_dist(float d) nuclear@2: { nuclear@2: focus_dist = d; nuclear@2: nuclear@2: cam_separation(d / 30.0); nuclear@2: } nuclear@2: nuclear@2: void cam_view_matrix(void) nuclear@2: { nuclear@2: cam_stereo_view_matrix(CAM_CENTER); nuclear@2: } nuclear@2: nuclear@2: void cam_stereo_view_matrix(int eye) nuclear@2: { nuclear@2: static const float offs_sign[] = {0.0f, 0.5f, -0.5f}; /* center, left, right */ nuclear@2: float offs = eye_sep * offs_sign[eye]; nuclear@2: nuclear@2: gl_translatef(offs, 0, 0); nuclear@2: nuclear@2: gl_translatef(0, 0, -cam_dist); nuclear@2: gl_rotatef(cam_phi, 1, 0, 0); nuclear@2: gl_rotatef(cam_theta, 0, 1, 0); nuclear@2: gl_translatef(-cam_pos.x, -cam_pos.y, -cam_pos.z); nuclear@2: } nuclear@2: nuclear@2: void cam_proj_matrix(void) nuclear@2: { nuclear@2: cam_stereo_proj_matrix(CAM_CENTER); nuclear@2: } nuclear@2: nuclear@2: void cam_stereo_proj_matrix(int eye) nuclear@2: { nuclear@2: float vfov_rad = M_PI * vfov / 180.0; nuclear@2: float top = nearclip * tan(vfov_rad * 0.5); nuclear@2: float right = top * aspect; nuclear@2: nuclear@2: static const float offs_sign[] = {0.0f, 1.0, -1.0}; /* center, left, right */ nuclear@2: float frust_shift = offs_sign[eye] * (eye_sep * 0.5 * nearclip / focus_dist); nuclear@2: nuclear@2: gl_frustum(-right + frust_shift, right + frust_shift, -top, top, nearclip, farclip); nuclear@2: }