208 lines · 5.9 KB · C++
RawDownload
////  Camera.cpp//  interface////  Copyright (c) 2013 High Fidelity, Inc. All rights reserved. #include <glm/gtx/quaternion.hpp> #include <SharedUtil.h>#include <VoxelConstants.h> #include "Camera.h"#include "Util.h" const float CAMERA_MINIMUM_MODE_SHIFT_RATE     = 0.5f; const float CAMERA_FIRST_PERSON_MODE_UP_SHIFT  = 0.0f;const float CAMERA_FIRST_PERSON_MODE_DISTANCE  = 0.0f;const float CAMERA_FIRST_PERSON_MODE_TIGHTNESS = 100.0f; const float CAMERA_THIRD_PERSON_MODE_UP_SHIFT  = -0.2f;const float CAMERA_THIRD_PERSON_MODE_DISTANCE  = 1.5f;const float CAMERA_THIRD_PERSON_MODE_TIGHTNESS = 8.0f; const float CAMERA_MIRROR_MODE_UP_SHIFT        = 0.0f;const float CAMERA_MIRROR_MODE_DISTANCE        = 0.3f;const float CAMERA_MIRROR_MODE_TIGHTNESS       = 100.0f;  Camera::Camera() {     _needsToInitialize   = true;    _frustumNeedsReshape = true;        _modeShift         = 1.0f;    _modeShiftRate     = 1.0f;    _linearModeShift   = 0.0f;    _mode              = CAMERA_MODE_THIRD_PERSON;    _tightness         = 10.0f; // default    _fieldOfView       = DEFAULT_FIELD_OF_VIEW_DEGREES;     _aspectRatio       = 16.f/9.f;    _nearClip          = 0.08f; // default    _farClip           = 50.0f * TREE_SCALE; // default    _upShift           = 0.0f;    _distance          = 0.0f;    _previousUpShift   = 0.0f;    _previousDistance  = 0.0f;    _previousTightness = 0.0f;    _newUpShift        = 0.0f;    _newDistance       = 0.0f;    _newTightness      = 0.0f;    _targetPosition    = glm::vec3(0.0f, 0.0f, 0.0f);    _position          = glm::vec3(0.0f, 0.0f, 0.0f);    _idealPosition     = glm::vec3(0.0f, 0.0f, 0.0f);    _scale             = 1.0f;} void Camera::update(float deltaTime)  {     if (_mode != CAMERA_MODE_NULL) {        // use iterative forces to push the camera towards the target position and angle        updateFollowMode(deltaTime);     }} // use iterative forces to keep the camera at the desired position and anglevoid Camera::updateFollowMode(float deltaTime) {       if (_linearModeShift < 1.0f) {        _linearModeShift += _modeShiftRate * deltaTime;                _modeShift = ONE_HALF - ONE_HALF * cosf(_linearModeShift * PIE );         _upShift   = _previousUpShift   * (1.0f - _modeShift) + _newUpShift   * _modeShift;        _distance  = _previousDistance  * (1.0f - _modeShift) + _newDistance  * _modeShift;        _tightness = _previousTightness * (1.0f - _modeShift) + _newTightness * _modeShift;         if (_needsToInitialize || _linearModeShift > 1.0f) {            _linearModeShift = 1.0f;            _modeShift = 1.0f;            _upShift   = _newUpShift;            _distance  = _newDistance;            _tightness = _newTightness;        }    }     // derive t from tightness    float t = _tightness * _modeShift * deltaTime;	    if (t > 1.0) {        t = 1.0;    }        // Update position and rotation, setting directly if tightness is 0.0        if (_needsToInitialize || (_tightness == 0.0f)) {        _rotation = _targetRotation;        _idealPosition = _targetPosition + _scale * (_rotation * glm::vec3(0.0f, _upShift, _distance));        _position = _idealPosition;        _needsToInitialize = false;     } else {        // pull rotation towards ideal        _rotation = safeMix(_rotation, _targetRotation, t);        _idealPosition = _targetPosition + _scale * (_rotation * glm::vec3(0.0f, _upShift, _distance));        _position += (_idealPosition - _position) * t;    }} float Camera::getFarClip() const {    return (_scale * _farClip < std::numeric_limits<int16_t>::max())            ? _scale * _farClip            : std::numeric_limits<int16_t>::max() - 1;} void Camera::setModeShiftRate ( float rate ) {        _modeShiftRate = rate;        if (_modeShiftRate < CAMERA_MINIMUM_MODE_SHIFT_RATE ) {        _modeShiftRate = CAMERA_MINIMUM_MODE_SHIFT_RATE;    }} void Camera::setMode(CameraMode m) {      _mode = m;    _modeShift = 0.0;    _linearModeShift = 0.0;        _previousUpShift   = _upShift;    _previousDistance  = _distance;    _previousTightness = _tightness;     if (_mode == CAMERA_MODE_THIRD_PERSON) {        _newUpShift   = CAMERA_THIRD_PERSON_MODE_UP_SHIFT;        _newDistance  = CAMERA_THIRD_PERSON_MODE_DISTANCE;        _newTightness = CAMERA_THIRD_PERSON_MODE_TIGHTNESS;            } else if (_mode == CAMERA_MODE_FIRST_PERSON) {        _newUpShift   = CAMERA_FIRST_PERSON_MODE_UP_SHIFT;        _newDistance  = CAMERA_FIRST_PERSON_MODE_DISTANCE;        _newTightness = CAMERA_FIRST_PERSON_MODE_TIGHTNESS;            } else if (_mode == CAMERA_MODE_MIRROR) {        _newUpShift   = CAMERA_MIRROR_MODE_UP_SHIFT;        _newDistance  = CAMERA_MIRROR_MODE_DISTANCE;        _newTightness = CAMERA_MIRROR_MODE_TIGHTNESS;    }}  void Camera::setTargetRotation( const glm::quat& targetRotation ) {    _targetRotation = targetRotation;} void Camera::setFieldOfView(float f) {     _fieldOfView = f;     _frustumNeedsReshape = true; } void Camera::setAspectRatio(float a) {     _aspectRatio = a;     _frustumNeedsReshape = true; } void Camera::setNearClip   (float n) {     _nearClip = n;     _frustumNeedsReshape = true; } void Camera::setFarClip    (float f) {     _farClip = f;     _frustumNeedsReshape = true; } void Camera::setEyeOffsetPosition  (const glm::vec3& p) {    _eyeOffsetPosition = p;    _frustumNeedsReshape = true;} void Camera::setEyeOffsetOrientation  (const glm::quat& o) {    _eyeOffsetOrientation = o;    _frustumNeedsReshape = true;} void Camera::setScale(float s) {    _scale = s;    _needsToInitialize = true;    _frustumNeedsReshape = true;} void Camera::initialize() {    _needsToInitialize = true;    _modeShift = 0.0;} // call to find out if the view frustum needs to be reshapedbool Camera::getFrustumNeedsReshape() const {    return _frustumNeedsReshape;} // call this after reshaping the view frustumvoid Camera::setFrustumWasReshaped() {    _frustumNeedsReshape = false;}