created transitions between camera modes

This commit is contained in:
Jeffrey Ventrella 2013-05-13 16:53:45 -07:00
parent 6c3de00bcd
commit 54010d36c4
3 changed files with 83 additions and 56 deletions

View file

@ -12,6 +12,8 @@
#include "Camera.h"
const float MODE_SHIFT_RATE = 5.0f;
Camera::Camera() {
_needsToInitialize = true;
@ -22,12 +24,10 @@ Camera::Camera() {
_fieldOfView = 60.0; // default
_nearClip = 0.08; // default
_farClip = 50.0 * TREE_SCALE; // default
_modeShift = 0.0;
_yaw = 0.0;
_pitch = 0.0;
_roll = 0.0;
_upShift = 0.0;
_rightShift = 0.0;
_distance = 0.0;
_idealYaw = 0.0;
_idealPitch = 0.0;
@ -36,28 +36,27 @@ Camera::Camera() {
_position = glm::vec3(0.0, 0.0, 0.0);
_idealPosition = glm::vec3(0.0, 0.0, 0.0);
_orientation.setToIdentity();
for (int m = 0; m < NUM_CAMERA_MODES; m ++) {
_attributes[m].upShift = 0.0f;
_attributes[m].distance = 0.0f;
_attributes[m].tightness = 0.0f;
}
}
void Camera::update(float deltaTime) {
if (_mode == CAMERA_MODE_NULL) {
_modeShift = 0.0;
} else {
// use iterative forces to push the camera towards the desired position and angle
if (_mode != CAMERA_MODE_NULL) {
// use iterative forces to push the camera towards the target position and angle
updateFollowMode(deltaTime);
if (_modeShift < 1.0f) {
_modeShift += MODE_SHIFT_RATE * deltaTime;
if (_modeShift > 1.0f) {
_modeShift = 1.0f;
}
}
}
}
// do this AFTER making any changes to yaw pitch and roll....
generateOrientation();
}
// generate the ortho-normals for the orientation based on the three Euler angles
void Camera::generateOrientation() {
_orientation.setToIdentity();
@ -74,7 +73,7 @@ void Camera::updateFollowMode(float deltaTime) {
if (t > 1.0) {
t = 1.0;
}
// update Euler angles (before position!)
if (_needsToInitialize || OculusManager::isConnected()) {
_yaw = _idealYaw;
@ -104,15 +103,27 @@ void Camera::updateFollowMode(float deltaTime) {
_position = _idealPosition;
_needsToInitialize = false;
} else {
// pull position towards ideal position
// force position towards ideal position
_position += (_idealPosition - _position) * t;
}
//transition to the attributes of the current mode
_upShift += (_attributes[_mode].upShift - _upShift ) * deltaTime * MODE_SHIFT_RATE;
_distance += (_attributes[_mode].distance - _distance ) * deltaTime * MODE_SHIFT_RATE;
_tightness += (_attributes[_mode].tightness - _tightness) * deltaTime * MODE_SHIFT_RATE;
}
void Camera::setMode(CameraMode m, CameraFollowingAttributes a) {
_attributes[m].upShift = a.upShift;
_attributes[m].distance = a.distance;
_attributes[m].tightness = a.tightness;
setMode(m);
}
void Camera::setMode(CameraMode m) {
_mode = m;
_modeShift = 0.0f;
_needsToInitialize = true;
}

View file

@ -20,13 +20,18 @@ enum CameraMode
NUM_CAMERA_MODES
};
const float MODE_SHIFT_RATE = 2.0f;
class Camera
{
public:
Camera();
struct CameraFollowingAttributes
{
float upShift;
float distance;
float tightness;
};
void initialize(); // instantly put the camera at the ideal position and rotation.
void update( float deltaTime );
@ -35,7 +40,6 @@ public:
void setPitch ( float p ) { _pitch = p; }
void setRoll ( float r ) { _roll = r; }
void setUpShift ( float u ) { _upShift = u; }
void setRightShift ( float r ) { _rightShift = r; }
void setDistance ( float d ) { _distance = d; }
void setTargetPosition( glm::vec3 t ) { _targetPosition = t; }
void setTargetYaw ( float y ) { _idealYaw = y; }
@ -43,8 +47,8 @@ public:
void setTightness ( float t ) { _tightness = t; }
void setTargetRotation( float yaw, float pitch, float roll );
void setMode ( CameraMode m );
void setMode ( CameraMode m, CameraFollowingAttributes attributes );
void setFieldOfView ( float f );
void setAspectRatio ( float a );
void setNearClip ( float n );
@ -56,7 +60,6 @@ public:
glm::vec3 getPosition () { return _position; }
Orientation getOrientation() { return _orientation; }
CameraMode getMode () { return _mode; }
float getModeShift () { return _modeShift; }
float getFieldOfView() { return _fieldOfView; }
float getAspectRatio() { return _aspectRatio; }
float getNearClip () { return _nearClip; }
@ -68,7 +71,6 @@ private:
bool _needsToInitialize;
CameraMode _mode;
float _modeShift; // 0.0 to 1.0
bool _frustumNeedsReshape;
glm::vec3 _position;
glm::vec3 _idealPosition;
@ -81,13 +83,14 @@ private:
float _pitch;
float _roll;
float _upShift;
float _rightShift;
float _idealYaw;
float _idealPitch;
float _idealRoll;
float _distance;
float _tightness;
Orientation _orientation;
CameraFollowingAttributes _attributes[NUM_CAMERA_MODES];
void generateOrientation();
void updateFollowMode( float deltaTime );

View file

@ -114,9 +114,6 @@ float MOUSE_VIEW_SHIFT_PITCH_MARGIN = (float)(::screenHeight * 0.2f);
float MOUSE_VIEW_SHIFT_YAW_LIMIT = 45.0;
float MOUSE_VIEW_SHIFT_PITCH_LIMIT = 30.0;
//CameraMode defaultCameraMode = CAMERA_MODE_FIRST_PERSON;
CameraMode defaultCameraMode = CAMERA_MODE_THIRD_PERSON;
bool wantColorRandomizer = true; // for addSphere and load file
Oscilloscope audioScope(256,200,true);
@ -335,7 +332,12 @@ void init(void) {
}
myAvatar.setPosition(start_location);
myCamera.setMode(defaultCameraMode);
Camera::CameraFollowingAttributes a;
a.upShift = -0.2f;
a.distance = 1.5f;
a.tightness = 8.0f;
myCamera.setMode(CAMERA_MODE_THIRD_PERSON, a);
myAvatar.setDisplayingHead(true);
OculusManager::connect();
@ -1044,37 +1046,28 @@ void display(void)
glLoadIdentity();
// camera settings
if (myCamera.getMode() == CAMERA_MODE_MIRROR) {
myAvatar.setDisplayingHead(true);
myCamera.setUpShift (0.0);
myCamera.setDistance (0.2);
myCamera.setTightness (100.0f);
myCamera.setTargetPosition(myAvatar.getHeadPosition());
myCamera.setTargetRotation(myAvatar.getBodyYaw() - 180.0f, 0.0f, 0.0f);
} else if (myCamera.getMode() == CAMERA_MODE_FIRST_PERSON || OculusManager::isConnected()) {
myAvatar.setDisplayingHead(false);
if (OculusManager::isConnected()) {
myAvatar.setDisplayingHead(false);
myCamera.setUpShift (0.0f);
myCamera.setDistance (0.0f);
myCamera.setTightness (100.0f);
myCamera.setTargetPosition(myAvatar.getHeadPosition());
myCamera.setTargetRotation(myAvatar.getBodyYaw() + myAvatar.getHeadYaw(), -myAvatar.getHeadPitch(), myAvatar.getHeadRoll());
} else if (myCamera.getMode() == CAMERA_MODE_MIRROR) {
myCamera.setTargetPosition(myAvatar.getSpringyHeadPosition());
myCamera.setTargetRotation(myAvatar.getBodyYaw() - 180.0f, 0.0f, 0.0f);
if (OculusManager::isConnected()) {
myCamera.setTargetRotation(myAvatar.getBodyYaw() + myAvatar.getHeadYaw(),
-myAvatar.getHeadPitch(),
myAvatar.getHeadRoll());
} else {
myCamera.setTargetRotation(myAvatar.getAbsoluteHeadYaw()- mouseViewShiftYaw, myAvatar.getRenderPitch() + mouseViewShiftPitch, 0.0f);
} else {
if (myCamera.getMode() == CAMERA_MODE_FIRST_PERSON) {
myCamera.setTargetPosition(myAvatar.getSpringyHeadPosition());
myCamera.setTargetRotation(myAvatar.getAbsoluteHeadYaw()- mouseViewShiftYaw, myAvatar.getRenderPitch() + mouseViewShiftPitch, 0.0f);
} else if (myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
myCamera.setTargetPosition(myAvatar.getHeadPosition());
myCamera.setTargetRotation(myAvatar.getBodyYaw() - mouseViewShiftYaw, mouseViewShiftPitch, 0.0f);
}
} else if (myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
myAvatar.setDisplayingHead(true);
myCamera.setUpShift (-0.2f);
myCamera.setDistance (1.5f);
myCamera.setTightness (8.0f);
myCamera.setTargetPosition(myAvatar.getHeadPosition());
myCamera.setTargetRotation(myAvatar.getBodyYaw() - mouseViewShiftYaw, mouseViewShiftPitch, 0.0f);
}
// important...
myCamera.update( 1.f/FPS );
@ -1245,9 +1238,19 @@ int setRenderFirstPerson(int state) {
bool value = setValue(state, &::renderFirstPersonOn);
if (state == MENU_ROW_PICKED) {
if (::renderFirstPersonOn) {
myCamera.setMode(CAMERA_MODE_FIRST_PERSON);
Camera::CameraFollowingAttributes a;
a.upShift = 0.0f;
a.distance = 0.0f;
a.tightness = 100.0f;
myCamera.setMode(CAMERA_MODE_FIRST_PERSON, a);
myAvatar.setDisplayingHead(false);
} else {
myCamera.setMode(CAMERA_MODE_THIRD_PERSON);
Camera::CameraFollowingAttributes a;
a.upShift = -0.2f;
a.distance = 1.5f;
a.tightness = 8.0f;
myCamera.setMode(CAMERA_MODE_THIRD_PERSON, a);
myAvatar.setDisplayingHead(true);
}
}
return value;
@ -1681,9 +1684,19 @@ void key(unsigned char k, int x, int y) {
audio.setMixerLoopbackFlag(::lookingInMirror);
if (::lookingInMirror) {
myCamera.setMode(CAMERA_MODE_MIRROR);
Camera::CameraFollowingAttributes a;
a.upShift = 0.0f;
a.distance = 0.2f;
a.tightness = 100.0f;
myCamera.setMode(CAMERA_MODE_MIRROR, a);
myAvatar.setDisplayingHead(true);
} else {
myCamera.setMode(defaultCameraMode);
Camera::CameraFollowingAttributes a;
a.upShift = -0.2f;
a.distance = 1.5f;
a.tightness = 8.0f;
myCamera.setMode(CAMERA_MODE_THIRD_PERSON, a);
myAvatar.setDisplayingHead(true);
}
#endif
}