nuclear@5: #include "opengl.h" nuclear@5: #include "camera.h" nuclear@10: #include "vr.h" nuclear@5: nuclear@5: Camera::Camera() nuclear@5: { nuclear@10: roll = 0.0; nuclear@5: inval_cache(); nuclear@5: } nuclear@5: nuclear@5: Camera::~Camera() nuclear@5: { nuclear@5: } nuclear@5: nuclear@5: void Camera::calc_inv_matrix(Matrix4x4 *mat) const nuclear@5: { nuclear@5: *mat = matrix().inverse(); nuclear@5: } nuclear@5: nuclear@5: const Matrix4x4 &Camera::matrix() const nuclear@5: { nuclear@5: if(!mcache.valid) { nuclear@5: calc_matrix(&mcache.mat); nuclear@5: mcache.valid = true; nuclear@5: } nuclear@5: return mcache.mat; nuclear@5: } nuclear@5: nuclear@5: const Matrix4x4 &Camera::inv_matrix() const nuclear@5: { nuclear@5: if(!mcache_inv.valid) { nuclear@5: calc_inv_matrix(&mcache_inv.mat); nuclear@5: mcache_inv.valid = true; nuclear@5: } nuclear@5: return mcache_inv.mat; nuclear@5: } nuclear@5: nuclear@5: void Camera::use() const nuclear@5: { nuclear@9: mult_matrix(matrix()); nuclear@5: } nuclear@5: nuclear@5: void Camera::use_inverse() const nuclear@5: { nuclear@9: mult_matrix(inv_matrix()); nuclear@5: } nuclear@5: nuclear@5: void Camera::input_move(float x, float y, float z) nuclear@5: { nuclear@5: } nuclear@5: nuclear@5: void Camera::input_rotate(float x, float y, float z) nuclear@5: { nuclear@5: } nuclear@5: nuclear@5: void Camera::input_zoom(float factor) nuclear@5: { nuclear@5: } nuclear@5: nuclear@5: nuclear@5: // ---- orbit camera ---- nuclear@5: nuclear@5: OrbitCamera::OrbitCamera() nuclear@5: { nuclear@5: theta = 0.0; nuclear@5: phi = 0.0; nuclear@5: rad = 10.0; nuclear@5: } nuclear@5: nuclear@5: OrbitCamera::~OrbitCamera() nuclear@5: { nuclear@5: } nuclear@5: nuclear@5: void OrbitCamera::calc_matrix(Matrix4x4 *mat) const nuclear@5: { nuclear@5: mat->reset_identity(); nuclear@5: mat->translate(Vector3(0, 0, -rad)); nuclear@5: mat->rotate(Vector3(phi, 0, 0)); nuclear@5: mat->rotate(Vector3(0, theta, 0)); nuclear@10: mat->rotate(Vector3(0, 0, roll)); nuclear@5: } nuclear@5: nuclear@5: void OrbitCamera::calc_inv_matrix(Matrix4x4 *mat) const nuclear@5: { nuclear@5: mat->reset_identity(); nuclear@10: mat->rotate(Vector3(0, 0, roll)); nuclear@5: mat->rotate(Vector3(0, theta, 0)); nuclear@5: mat->rotate(Vector3(phi, 0, 0)); nuclear@5: mat->translate(Vector3(0, 0, -rad)); nuclear@5: } nuclear@5: nuclear@5: void OrbitCamera::input_rotate(float x, float y, float z) nuclear@5: { nuclear@9: theta += y; nuclear@9: phi += x; nuclear@10: roll += z; nuclear@5: nuclear@5: if(phi < -M_PI / 2) nuclear@5: phi = -M_PI / 2; nuclear@5: if(phi > M_PI) nuclear@5: phi = M_PI; nuclear@5: nuclear@5: inval_cache(); nuclear@5: } nuclear@5: nuclear@5: void OrbitCamera::input_zoom(float factor) nuclear@5: { nuclear@5: rad += factor; nuclear@5: if(rad < 0.0) nuclear@5: rad = 0.0; nuclear@5: nuclear@5: inval_cache(); nuclear@5: } nuclear@5: nuclear@9: void FpsCamera::calc_matrix(Matrix4x4 *mat) const nuclear@9: { nuclear@9: mat->reset_identity(); nuclear@9: mat->translate(Vector3(pos.x, pos.y, pos.z)); nuclear@9: mat->rotate(Vector3(0, theta, 0)); nuclear@9: mat->rotate(Vector3(phi, 0, 0)); nuclear@10: mat->rotate(Vector3(0, 0, roll)); nuclear@9: } nuclear@9: nuclear@9: void FpsCamera::calc_inv_matrix(Matrix4x4 *mat) const nuclear@9: { nuclear@9: mat->reset_identity(); nuclear@10: mat->rotate(Vector3(0, 0, roll)); nuclear@9: mat->rotate(Vector3(phi, 0, 0)); nuclear@9: mat->rotate(Vector3(0, theta, 0)); nuclear@9: mat->translate(Vector3(-pos.x, -pos.y, -pos.z)); nuclear@9: } nuclear@9: nuclear@9: void FpsCamera::input_move(float x, float y, float z) nuclear@9: { nuclear@9: pos.x += x * cos(theta) - z * sin(theta); nuclear@9: pos.z += x * sin(theta) + z * cos(theta); nuclear@9: pos.y += y; nuclear@9: inval_cache(); nuclear@9: } nuclear@9: nuclear@9: const Vector3 &FpsCamera::get_position() const nuclear@9: { nuclear@9: return pos; nuclear@9: } nuclear@9: nuclear@9: nuclear@5: FlyCamera::FlyCamera() nuclear@5: { nuclear@5: pos.z = 10.0f; nuclear@5: } nuclear@5: nuclear@5: void FlyCamera::calc_matrix(Matrix4x4 *mat) const nuclear@5: { nuclear@9: Matrix3x3 rmat = rot.get_rotation_matrix().transposed(); nuclear@9: Matrix4x4 tmat; nuclear@9: tmat.set_translation(pos); nuclear@9: *mat = tmat * Matrix4x4(rmat); nuclear@5: } nuclear@5: nuclear@5: /*void FlyCamera::calc_inv_matrix(Matrix4x4 *mat) const nuclear@5: { nuclear@5: }*/ nuclear@5: nuclear@5: const Vector3 &FlyCamera::get_position() const nuclear@5: { nuclear@5: return pos; nuclear@5: } nuclear@5: nuclear@5: const Quaternion &FlyCamera::get_rotation() const nuclear@5: { nuclear@5: return rot; nuclear@5: } nuclear@5: nuclear@5: void FlyCamera::input_move(float x, float y, float z) nuclear@5: { nuclear@9: static const Vector3 vfwd(0, 0, 1), vright(1, 0, 0); nuclear@9: nuclear@9: Vector3 k = vfwd.transformed(rot); nuclear@9: Vector3 i = vright.transformed(rot); nuclear@9: Vector3 j = cross_product(k, i); nuclear@9: nuclear@9: pos += i * x + j * y + k * z; nuclear@5: inval_cache(); nuclear@5: } nuclear@5: nuclear@5: void FlyCamera::input_rotate(float x, float y, float z) nuclear@5: { nuclear@5: Vector3 axis(x, y, z); nuclear@5: float axis_len = axis.length(); nuclear@5: rot.rotate(axis / axis_len, axis_len); nuclear@5: rot.normalize(); nuclear@9: nuclear@5: inval_cache(); nuclear@5: } nuclear@10: nuclear@10: nuclear@10: // --- VR additions --- nuclear@11: VRFpsCamera::VRFpsCamera() nuclear@11: { nuclear@11: neck_eye_dist = 0.14; // default neck->eye distance 14cm nuclear@11: } nuclear@11: nuclear@11: void VRFpsCamera::calc_matrix(Matrix4x4 *mat) const nuclear@11: { nuclear@11: mat->reset_identity(); nuclear@11: mat->translate(Vector3(pos.x, pos.y, pos.z)); nuclear@11: mat->rotate(Vector3(0, theta, 0)); nuclear@11: mat->rotate(Vector3(phi, 0, 0)); nuclear@11: mat->rotate(Vector3(0, 0, roll)); nuclear@11: mat->translate(Vector3(0, neck_eye_dist, 0)); nuclear@11: } nuclear@11: nuclear@11: void VRFpsCamera::calc_inv_matrix(Matrix4x4 *mat) const nuclear@11: { nuclear@11: mat->reset_identity(); nuclear@11: mat->translate(Vector3(0, -neck_eye_dist, 0)); nuclear@11: mat->rotate(Vector3(0, 0, roll)); nuclear@11: mat->rotate(Vector3(phi, 0, 0)); nuclear@11: mat->rotate(Vector3(0, theta, 0)); nuclear@11: mat->translate(Vector3(-pos.x, -pos.y, -pos.z)); nuclear@11: } nuclear@10: nuclear@10: void VRFpsCamera::track_vr() nuclear@10: { nuclear@10: float euler[3]; nuclear@10: vr_get_rotation_euler(euler); nuclear@10: nuclear@10: // input_rotate invalidates cache nuclear@10: input_rotate(prev_angles[0] - euler[0], prev_angles[1] - euler[1], prev_angles[2] - euler[2]); nuclear@10: nuclear@10: prev_angles[0] = euler[0]; nuclear@10: prev_angles[1] = euler[1]; nuclear@10: prev_angles[2] = euler[2]; nuclear@10: } nuclear@10: