(1) re-designed and debugged the orientation class and cleaned up quaternion code, and fixed issues in camera and main related to yaw and camera transforms (2) improved hand-holding algorithm

This commit is contained in:
Jeffrey Ventrella 2013-05-01 13:00:08 -07:00
parent 6b66d8e789
commit b388e9a760
9 changed files with 247 additions and 296 deletions

View file

@ -107,13 +107,14 @@ Avatar::Avatar(bool isMine) {
_head.lastLoudness = 0.0;
_head.browAudioLift = 0.0;
_head.noise = 0;
_movedHandOffset = glm::vec3( 0.0, 0.0, 0.0 );
_usingBodySprings = true;
_renderYaw = 0.0;
_renderPitch = 0.0;
_sphere = NULL;
_interactingOther = NULL;
_interactingOtherIsNearby = false;
_closeEnoughToHoldHands = false;
_handHoldingPosition = glm::vec3( 0.0, 0.0, 0.0 );
initializeSkeleton();
@ -136,7 +137,7 @@ Avatar::Avatar(const Avatar &otherAvatar) {
_velocity = otherAvatar._velocity;
_thrust = otherAvatar._thrust;
_rotation = otherAvatar._rotation;
_interactingOtherIsNearby = otherAvatar._interactingOtherIsNearby;
_closeEnoughToHoldHands = otherAvatar._closeEnoughToHoldHands;
_bodyYaw = otherAvatar._bodyYaw;
_bodyPitch = otherAvatar._bodyPitch;
_bodyRoll = otherAvatar._bodyRoll;
@ -301,18 +302,18 @@ void Avatar::simulate(float deltaTime) {
// reset hand and arm positions according to hand movement
updateHandMovement( deltaTime );
if ( !_interactingOtherIsNearby ) {
if ( !_closeEnoughToHoldHands ) {
//initialize _handHolding
_handHoldingPosition = _bone[ AVATAR_BONE_RIGHT_HAND ].position;
}
_interactingOtherIsNearby = false;
_closeEnoughToHoldHands = false; // reset for the next go-round
// if the avatar being simulated is mine, then loop through
// all the other avatars for potential interactions...
if ( _isMine )
{
float closestDistance = 10000.0f;
//float closestDistance = 10000.0f;
AgentList* agentList = AgentList::getInstance();
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
@ -329,20 +330,29 @@ void Avatar::simulate(float deltaTime) {
float distance = glm::length( v );
if ( distance < _maxArmLength + _maxArmLength ) {
closestDistance = distance;
//closestDistance = distance;
_interactingOther = otherAvatar;
_interactingOtherIsNearby = true;
_closeEnoughToHoldHands = true;
// if I am holding hands with another avatar, a force is applied
if (( _handState == 1 ) || ( _interactingOther->_handState == 1 )) {
glm::vec3 vectorToOtherHand = _interactingOther->_handPosition - _handHoldingPosition;
glm::vec3 vectorToMyHand = _bone[ AVATAR_BONE_RIGHT_HAND ].position - _handHoldingPosition;
_handHoldingPosition += vectorToOtherHand * YOUR_HAND_HOLDING_PULL;
_handHoldingPosition += vectorToMyHand * MY_HAND_HOLDING_PULL;
_bone[ AVATAR_BONE_RIGHT_HAND ].position = _handHoldingPosition;
}
// if the hands are close enough to grasp...
//if (distance < 0.1)
{
glm::vec3 vectorToOtherHand = _interactingOther->_handPosition - _handHoldingPosition;
glm::vec3 vectorToMyHand = _bone[ AVATAR_BONE_RIGHT_HAND ].position - _handHoldingPosition;
_handHoldingPosition += vectorToOtherHand * YOUR_HAND_HOLDING_PULL;
_handHoldingPosition += vectorToMyHand * MY_HAND_HOLDING_PULL;
_bone[ AVATAR_BONE_RIGHT_HAND ].position = _handHoldingPosition;
_avatarTouch.setYourHandPosition( _interactingOther->_handPosition );
//if ( glm::length(vectorToOtherHand) > 0.2 ) {
// _velocity += vectorToOtherHand;
//}
}
}
}
}
}
@ -350,19 +360,24 @@ void Avatar::simulate(float deltaTime) {
// Set the vector we send for hand position to other people to be our right hand
setHandPosition(_bone[ AVATAR_BONE_RIGHT_HAND ].position);
//update the effects of touching another avatar
_avatarTouch.simulate(deltaTime);
//update the effects of touching another avatar
}//if ( _isMine )
//constrain right arm length and re-adjust elbow position as it bends
updateArmIKAndConstraints( deltaTime );
if (_isMine) {
_avatarTouch.setMyHandPosition( _bone[ AVATAR_BONE_RIGHT_HAND ].position );
// set hand positions for _avatarTouch.setMyHandPosition AFTER calling updateArmIKAndConstraints
if ( _interactingOther != NULL ) {
if (_isMine) {
_avatarTouch.setMyHandPosition ( _bone[ AVATAR_BONE_RIGHT_HAND ].position );
_avatarTouch.setYourHandPosition( _interactingOther->_handPosition );
_avatarTouch.setMyHandState ( _handState );
_avatarTouch.setYourHandState ( _interactingOther->_handState );
_avatarTouch.simulate(deltaTime);
}
}
if (!_interactingOtherIsNearby) {
if (!_closeEnoughToHoldHands) {
_interactingOther = NULL;
}
@ -429,9 +444,6 @@ void Avatar::simulate(float deltaTime) {
}
}
void Avatar::updateHead(float deltaTime) {
if (!_head.noise) {
// Decay back toward center
@ -488,7 +500,6 @@ void Avatar::updateHead(float deltaTime) {
_head.eyeballPitch[0] = _head.eyeballPitch[1] = -_headPitch + eye_target_pitch_adjust;
_head.eyeballYaw[0] = _head.eyeballYaw[1] = -_headYaw + eye_target_yaw_adjust;
}
if (_head.noise)
{
@ -603,18 +614,16 @@ void Avatar::updateCollisionWithOtherAvatar( Avatar * otherAvatar, float deltaTi
// push balls away from each other and apply friction
glm::vec3 ballPushForce = directionVector * COLLISION_BALL_FORCE * deltaTime;
float ballMomentum = COLLISION_BALL_FRICTION * deltaTime;
float ballMomentum = 1.0 - COLLISION_BALL_FRICTION * deltaTime;
if ( ballMomentum < 0.0 ) { ballMomentum = 0.0;}
_bone[b].springyVelocity += ballPushForce;
otherAvatar->_bone[o].springyVelocity -= ballPushForce;
_bone[b].springyVelocity *= 0.9;
otherAvatar->_bone[o].springyVelocity *= 0.9;
_bone[b].springyVelocity *= ballMomentum;
otherAvatar->_bone[o].springyVelocity *= ballMomentum;
// accumulate forces and frictions to the velocities of avatar bodies
// accumulate forces and frictions to apply to the velocities of avatar bodies
bodyPushForce += directionVector * COLLISION_BODY_FORCE * deltaTime;
bodyMomentum -= COLLISION_BODY_FRICTION * deltaTime;
if ( bodyMomentum < 0.0 ) { bodyMomentum = 0.0;}
@ -637,8 +646,6 @@ void Avatar::updateCollisionWithOtherAvatar( Avatar * otherAvatar, float deltaTi
} //method
void Avatar::setDisplayingHead( bool displayingHead ) {
_displayingHead = displayingHead;
}
@ -676,11 +683,8 @@ void Avatar::render(bool lookingInMirror) {
}
// if this is my avatar, then render my interactions with the other avatar
if ( _isMine )
{
if ( _interactingOtherIsNearby ) {
_avatarTouch.render();
}
if (( _isMine ) && ( _closeEnoughToHoldHands )) {
_avatarTouch.render();
}
// Render the balls
@ -739,7 +743,7 @@ void Avatar::renderHead(bool lookingInMirror) {
glEnable(GL_RESCALE_NORMAL);
// show head orientation
//renderOrientationDirections( _bone[ AVATAR_BONE_HEAD ].position, _bone[ AVATAR_BONE_HEAD ].orientation, 0.2f );
renderOrientationDirections( _bone[ AVATAR_BONE_HEAD ].springyPosition, _bone[ AVATAR_BONE_HEAD ].orientation, 0.2f );
glPushMatrix();
@ -812,9 +816,7 @@ void Avatar::renderHead(bool lookingInMirror) {
}
glPopMatrix();
// Mouth
glPushMatrix();
glTranslatef(0,-0.35,0.75);
glColor3f(0,0,0);
@ -1132,9 +1134,9 @@ void Avatar::updateHandMovement( float deltaTime ) {
glm::vec3 transformedHandMovement;
transformedHandMovement
= _orientation.getRight() * _movedHandOffset.x
+ _orientation.getUp() * -_movedHandOffset.y * 0.5f
+ _orientation.getFront() * -_movedHandOffset.y;
= _orientation.getRight() * _movedHandOffset.x * 2.0f
+ _orientation.getUp() * -_movedHandOffset.y * 1.0f
+ _orientation.getFront() * -_movedHandOffset.y * 1.0f;
_bone[ AVATAR_BONE_RIGHT_HAND ].position += transformedHandMovement;
@ -1168,7 +1170,10 @@ void Avatar::updateArmIKAndConstraints( float deltaTime ) {
// set elbow position
glm::vec3 newElbowPosition = _bone[ AVATAR_BONE_RIGHT_SHOULDER ].position;
newElbowPosition += armVector * ONE_HALF;
//glm::vec3 perpendicular = glm::cross( _orientation.getFront(), armVector );
glm::vec3 perpendicular = glm::cross( _orientation.getFront(), armVector );
newElbowPosition += perpendicular * ( 1.0f - ( _maxArmLength / distance ) ) * ONE_HALF;
_bone[ AVATAR_BONE_RIGHT_UPPER_ARM ].position = newElbowPosition;
@ -1238,6 +1243,7 @@ void Avatar::renderBody() {
}
}
/*
// if the hand is grasping, show it...
if (( _usingBodySprings ) && ( _handState == 1 )) {
glPushMatrix();
@ -1250,6 +1256,7 @@ void Avatar::renderBody() {
glPopMatrix();
}
*/
}
void Avatar::SetNewHeadTarget(float pitch, float yaw) {

View file

@ -72,7 +72,6 @@ enum AvatarBoneID
NUM_AVATAR_BONES
};
class Avatar : public AvatarData {
public:
Avatar(bool isMine);
@ -93,7 +92,7 @@ public:
float getBodyYaw() {return _bodyYaw;};
void addBodyYaw(float y) {_bodyYaw += y;};
bool getIsNearInteractingOther() { return _interactingOtherIsNearby; }
bool getIsNearInteractingOther() { return _closeEnoughToHoldHands; }
float getAbsoluteHeadYaw() const;
void setLeanForward(float dist);
@ -123,7 +122,7 @@ public:
void setDisplayingHead( bool displayingHead );
float getAverageLoudness() {return _head.averageLoudness;};
void setAverageLoudness(float al) {_head.averageLoudness = al;};
void setAverageLoudness(float al) {_head.averageLoudness = al;};
void SetNewHeadTarget(float, float);
@ -148,23 +147,17 @@ private:
const bool AVATAR_GRAVITY = true;
const float DECAY = 0.1;
const float THRUST_MAG = 1200.0;
const float YAW_MAG = 500.0; //JJV - changed from 300.0;
const float YAW_MAG = 500.0;
const float TEST_YAW_DECAY = 5.0;
const float LIN_VEL_DECAY = 5.0;
const float MY_HAND_HOLDING_PULL = 0.2;
const float YOUR_HAND_HOLDING_PULL = 1.0;
const float BODY_SPRING_FORCE = 6.0f;
const float BODY_SPRING_DECAY = 16.0f;
//const float COLLISION_FRICTION = 0.5;
//const float COLLISION_RADIUS_SCALAR = 1.8;
//const float COLLISION_BALL_FORCE = 0.1;
//const float COLLISION_BODY_FORCE = 3.0;
const float COLLISION_RADIUS_SCALAR = 1.8;
const float COLLISION_BALL_FORCE = 0.6;
const float COLLISION_BALL_FORCE = 1.0;
const float COLLISION_BODY_FORCE = 6.0;
const float COLLISION_BALL_FRICTION = 200.0;
const float COLLISION_BALL_FRICTION = 60.0;
const float COLLISION_BODY_FRICTION = 0.5;
struct AvatarBone
@ -223,37 +216,37 @@ private:
float audioAttack;
};
AvatarHead _head;
bool _isMine;
glm::vec3 _TEST_bigSpherePosition;
float _TEST_bigSphereRadius;
bool _mousePressed;
float _bodyYawDelta;
bool _usingBodySprings;
glm::vec3 _movedHandOffset;
glm::quat _rotation; // the rotation of the avatar body as a whole expressed as a quaternion
AvatarBone _bone[ NUM_AVATAR_BONES ];
AvatarMode _mode;
glm::vec3 _handHoldingPosition;
glm::vec3 _velocity;
glm::vec3 _thrust;
float _speed;
float _maxArmLength;
Orientation _orientation;
int _driveKeys[MAX_DRIVE_KEYS];
GLUquadric* _sphere;
float _renderYaw;
float _renderPitch; // Pitch from view frustum when this is own head
timeval _transmitterTimer;
float _transmitterHz;
int _transmitterPackets;
Avatar* _interactingOther;
bool _interactingOtherIsNearby;
float _pelvisStandingHeight;
float _height;
Balls* _balls;
AvatarTouch _avatarTouch;
bool _displayingHead; // should be false if in first-person view
AvatarHead _head;
bool _isMine;
glm::vec3 _TEST_bigSpherePosition;
float _TEST_bigSphereRadius;
bool _mousePressed;
float _bodyYawDelta;
bool _usingBodySprings;
glm::vec3 _movedHandOffset;
glm::quat _rotation; // the rotation of the avatar body as a whole expressed as a quaternion
AvatarBone _bone[ NUM_AVATAR_BONES ];
AvatarMode _mode;
glm::vec3 _handHoldingPosition;
glm::vec3 _velocity;
glm::vec3 _thrust;
float _speed;
float _maxArmLength;
Orientation _orientation;
int _driveKeys[MAX_DRIVE_KEYS];
GLUquadric* _sphere;
float _renderYaw;
float _renderPitch; // Pitch from view frustum when this is own head
timeval _transmitterTimer;
float _transmitterHz;
int _transmitterPackets;
Avatar* _interactingOther;
bool _closeEnoughToHoldHands;
float _pelvisStandingHeight;
float _height;
Balls* _balls;
AvatarTouch _avatarTouch;
bool _displayingHead; // should be false if in first-person view
// private methods...
void initializeSkeleton();

View file

@ -11,11 +11,12 @@
#include "AvatarTouch.h"
#include "InterfaceConfig.h"
AvatarTouch::AvatarTouch() {
_myHandPosition = glm::vec3( 0.0f, 0.0f, 0.0f );
_yourHandPosition = glm::vec3( 0.0f, 0.0f, 0.0f );
_myHandState = 0;
_yourHandState = 0;
for (int p=0; p<NUM_POINTS; p++) {
_point[p] = glm::vec3( 0.0, 0.0, 0.0 );
@ -30,11 +31,39 @@ void AvatarTouch::setYourHandPosition( glm::vec3 position ) {
_yourHandPosition = position;
}
void AvatarTouch::setMyHandState( int state ) {
_myHandState = state;
}
void AvatarTouch::setYourHandState( int state ) {
_yourHandState = state;
}
void AvatarTouch::render() {
glm::vec3 v1( _myHandPosition );
glm::vec3 v2( _yourHandPosition );
// if my hand is grasping, show it...
if ( _myHandState == 1 ) {
glPushMatrix();
glTranslatef(_myHandPosition.x, _myHandPosition.y, _myHandPosition.z);
glColor4f( 1.0, 1.0, 0.8, 0.3 ); glutSolidSphere( 0.020f, 10.0f, 10.0f );
glColor4f( 1.0, 1.0, 0.4, 0.2 ); glutSolidSphere( 0.025f, 10.0f, 10.0f );
glColor4f( 1.0, 1.0, 0.2, 0.1 ); glutSolidSphere( 0.030f, 10.0f, 10.0f );
glPopMatrix();
}
// if your hand is grasping, show it...
if ( _yourHandState == 1 ) {
glPushMatrix();
glTranslatef(_yourHandPosition.x, _yourHandPosition.y, _yourHandPosition.z);
glColor4f( 1.0, 1.0, 0.8, 0.3 ); glutSolidSphere( 0.020f, 10.0f, 10.0f );
glColor4f( 1.0, 1.0, 0.4, 0.2 ); glutSolidSphere( 0.025f, 10.0f, 10.0f );
glColor4f( 1.0, 1.0, 0.2, 0.1 ); glutSolidSphere( 0.030f, 10.0f, 10.0f );
glPopMatrix();
}
glLineWidth( 2.0 );
glColor4f( 0.7f, 0.4f, 0.1f, 0.3 );
glBegin( GL_LINE_STRIP );

View file

@ -17,7 +17,9 @@ public:
void setMyHandPosition ( glm::vec3 position );
void setYourHandPosition( glm::vec3 position );
void simulate(float deltaTime);
void setMyHandState ( int state );
void setYourHandState ( int state );
void simulate (float deltaTime);
void render();
const float THREAD_RADIUS = 0.007;
@ -29,6 +31,8 @@ private:
glm::vec3 _point [NUM_POINTS];
glm::vec3 _myHandPosition;
glm::vec3 _yourHandPosition;
int _myHandState;
int _yourHandState;
};
#endif

View file

@ -34,12 +34,6 @@ Camera::Camera() {
void Camera::update( float deltaTime ) {
// generate the ortho-normals for the orientation based on the Euler angles
_orientation.setToIdentity();
_orientation.yaw ( _yaw );
_orientation.pitch( _pitch );
_orientation.roll ( _roll );
if ( _mode == CAMERA_MODE_NULL ) {
_modeShift = 0.0;
} else {
@ -53,6 +47,19 @@ void Camera::update( float deltaTime ) {
}
}
}
// 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();
_orientation.pitch( _pitch );
_orientation.yaw ( _yaw );
_orientation.roll ( _roll );
}
@ -71,9 +78,8 @@ void Camera::updateFollowMode( float deltaTime ) {
float radian = (_yaw / 180.0) * PIE;
// update _position
//these need to be checked to make sure they correspond to the correct coordinate system.
double x = _distance * -sin(radian);
double z = _distance * cos(radian);
double x = -_distance * sin(radian);
double z = -_distance * cos(radian);
double y = _upShift;
_idealPosition = _targetPosition + glm::vec3(x, y, z);

View file

@ -38,7 +38,6 @@ public:
void setTargetPosition( glm::vec3 t ) { _targetPosition = t; }
void setTargetYaw ( float y ) { _idealYaw = y; }
void setPosition ( glm::vec3 p ) { _position = p; }
void setOrientation ( Orientation o ) { _orientation.set(o); }
void setTightness ( float t ) { _tightness = t; }
void setMode ( CameraMode m );
@ -83,6 +82,7 @@ private:
float _tightness;
Orientation _orientation;
void generateOrientation();
void updateFollowMode( float deltaTime );
};

View file

@ -109,9 +109,9 @@ Oscilloscope audioScope(256,200,true);
ViewFrustum viewFrustum; // current state of view frustum, perspective, orientation, etc.
Avatar myAvatar(true); // The rendered avatar of oneself
Camera myCamera; // My view onto the world (sometimes on myself :)
Camera viewFrustumOffsetCamera; // The camera we use to sometimes show the view frustum from an offset mode
Avatar myAvatar(true); // The rendered avatar of oneself
Camera myCamera; // My view onto the world (sometimes on myself :)
Camera viewFrustumOffsetCamera; // The camera we use to sometimes show the view frustum from an offset mode
// Starfield information
char starFile[] = "https://s3-us-west-1.amazonaws.com/highfidelity/stars.txt";
@ -495,31 +495,19 @@ void loadViewFrustum(ViewFrustum& viewFrustum) {
glm::vec3 up;
glm::vec3 right;
float fov, nearClip, farClip;
float yaw, pitch, roll;
// Camera or Head?
if (::cameraFrustum) {
position = ::myCamera.getPosition();
position = ::myCamera.getPosition();
} else {
position = ::myAvatar.getHeadPosition();
position = ::myAvatar.getHeadPosition();
}
// This bit of hackery is all because our Cameras report the incorrect yaw.
// For whatever reason, the camera has a yaw set to 180.0-trueYaw, so we basically
// need to get the "yaw" from the camera and adjust it to be the trueYaw
yaw = -(::myCamera.getOrientation().getYaw()-180);
pitch = ::myCamera.getOrientation().getPitch();
roll = ::myCamera.getOrientation().getRoll();
fov = ::myCamera.getFieldOfView();
nearClip = ::myCamera.getNearClip();
farClip = ::myCamera.getFarClip();
// We can't use the camera's Orientation because of it's broken yaw. so we make a new
// correct orientation to get our vectors
Orientation o;
o.yaw(yaw);
o.pitch(pitch);
o.roll(roll);
Orientation o = ::myCamera.getOrientation();
direction = o.getFront();
up = o.getUp();
@ -713,7 +701,7 @@ void display(void)
if ( ::lookingInMirror ) {
// set the camera to looking at my own face
myCamera.setTargetPosition ( myAvatar.getHeadPosition() );
myCamera.setTargetYaw ( - myAvatar.getBodyYaw() );
myCamera.setTargetYaw ( myAvatar.getBodyYaw() - 180.0f ); // 180 degrees from body yaw
myCamera.setPitch ( 0.0 );
myCamera.setRoll ( 0.0 );
myCamera.setUpShift ( 0.0 );
@ -800,10 +788,10 @@ void display(void)
}
myCamera.setTargetPosition( myAvatar.getHeadPosition() );
myCamera.setTargetYaw ( 180.0 - myAvatar.getBodyYaw() );
myCamera.setTargetYaw ( myAvatar.getBodyYaw() );
myCamera.setRoll ( 0.0 );
}
// important...
myCamera.update( 1.f/FPS );
@ -821,7 +809,7 @@ void display(void)
if (::viewFrustumFromOffset && ::frustumOn) {
// set the camera to third-person view but offset so we can see the frustum
viewFrustumOffsetCamera.setTargetYaw( 180.0 - myAvatar.getBodyYaw() + ::viewFrustumOffsetYaw );
viewFrustumOffsetCamera.setTargetYaw( ::viewFrustumOffsetYaw + myAvatar.getBodyYaw() );
viewFrustumOffsetCamera.setPitch ( ::viewFrustumOffsetPitch );
viewFrustumOffsetCamera.setRoll ( ::viewFrustumOffsetRoll );
viewFrustumOffsetCamera.setUpShift ( ::viewFrustumOffsetUp );
@ -834,9 +822,11 @@ void display(void)
// could be myCamera (if in normal mode)
// or could be viewFrustumOffsetCamera if in offset mode
// I changed the ordering here - roll is FIRST (JJV)
glRotatef ( whichCamera.getRoll(), 0, 0, 1 );
glRotatef ( whichCamera.getPitch(), 1, 0, 0 );
glRotatef ( whichCamera.getYaw(), 0, 1, 0 );
glRotatef ( whichCamera.getRoll(), IDENTITY_FRONT.x, IDENTITY_FRONT.y, IDENTITY_FRONT.z );
glRotatef ( whichCamera.getPitch(), IDENTITY_RIGHT.x, IDENTITY_RIGHT.y, IDENTITY_RIGHT.z );
glRotatef ( 180.0 - whichCamera.getYaw(), IDENTITY_UP.x, IDENTITY_UP.y, IDENTITY_UP.z );
glTranslatef( -whichCamera.getPosition().x, -whichCamera.getPosition().y, -whichCamera.getPosition().z );
if (::starsOn) {

View file

@ -9,165 +9,97 @@
#include <SharedUtil.h>
#include "avatars_Log.h"
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
//#include "Util.h"
using avatars_lib::printLog;
// XXXBHG - this test has not yet been reworked to match the correct vector orientation
// of the coordinate system, so don't use it for now.
//
// tosh - yep, I noticed... :-)
//
static bool testingForNormalizationAndOrthogonality = false;
static const bool USING_QUATERNIONS = true;
Orientation::Orientation() {
setToIdentity();
}
void Orientation::setToIdentity() {
_yaw = 0.0;
_pitch = 0.0;
_roll = 0.0;
right = glm::vec3( -1.0f, 0.0f, 0.0f );
up = glm::vec3( 0.0f, 1.0f, 0.0f );
front = glm::vec3( 0.0f, 0.0f, 1.0f );
quat = glm::quat();
right = glm::vec3( IDENTITY_RIGHT );
up = glm::vec3( IDENTITY_UP );
front = glm::vec3( IDENTITY_FRONT );
}
void Orientation::set( Orientation o ) {
quat = o.quat;
right = o.right;
up = o.up;
front = o.front;
}
void Orientation::update() {
void Orientation::yaw( float angle ) {
float pitchRads = _pitch * PI_OVER_180;
float yawRads = _yaw * PI_OVER_180;
float rollRads = _roll * PI_OVER_180;
float radian = angle * PI_OVER_180;
glm::quat q(glm::vec3(pitchRads, -(yawRads), rollRads));
// Next, create a rotation matrix from that quaternion
glm::mat4 rotation;
rotation = glm::mat4_cast(q);
// Transform the original vectors by the rotation matrix to get the new vectors
glm::vec4 qup(0,1,0,0);
glm::vec4 qright(-1,0,0,0);
glm::vec4 qfront(0,0,1,0);
glm::vec4 upNew = qup*rotation;
glm::vec4 rightNew = qright*rotation;
glm::vec4 frontNew = qfront*rotation;
// Copy the answers to output vectors
up.x = upNew.x;
up.y = upNew.y;
up.z = upNew.z;
right.x = rightNew.x;
right.y = rightNew.y;
right.z = rightNew.z;
front.x = frontNew.x;
front.y = frontNew.y;
front.z = frontNew.z;
if ( testingForNormalizationAndOrthogonality ) { testForOrthogonalAndNormalizedVectors( EPSILON ); }
}
void Orientation::yaw(float angle) {
// remember the value for any future changes to other angles
_yaw = angle;
update();
if ( USING_QUATERNIONS ) {
rotateAndGenerateDirections( glm::quat( glm::vec3( 0.0f, -radian, 0.0f )) );
} else {
float s = sin(radian);
float c = cos(radian);
glm::vec3 cosineFront = front * c;
glm::vec3 cosineRight = right * c;
glm::vec3 sineFront = front * s;
glm::vec3 sineRight = right * s;
front = cosineFront - sineRight;
right = cosineRight + sineFront;
}
}
void Orientation::pitch( float angle ) {
// remember the value for any future changes to other angles
_pitch = angle;
update();
}
float radian = angle * PI_OVER_180;
if ( USING_QUATERNIONS ) {
rotateAndGenerateDirections( glm::quat( glm::vec3( radian, 0.0f, 0.0f ) ) );
} else {
float s = sin(radian);
float c = cos(radian);
glm::vec3 cosineUp = up * c;
glm::vec3 cosineFront = front * c;
glm::vec3 sineUp = up * s;
glm::vec3 sineFront = front * s;
up = cosineUp - sineFront;
front = cosineFront + sineUp;
}
}
void Orientation::roll( float angle ) {
_roll = angle;
update();
float radian = angle * PI_OVER_180;
if ( USING_QUATERNIONS ) {
rotateAndGenerateDirections( glm::quat( glm::vec3( 0.0f, 0.0f, radian )) );
} else {
float s = sin(radian);
float c = cos(radian);
glm::vec3 cosineUp = up * c;
glm::vec3 cosineRight = right * c;
glm::vec3 sineUp = up * s;
glm::vec3 sineRight = right * s;
up = cosineUp - sineRight;
right = cosineRight + sineUp;
}
}
void Orientation::rotateAndGenerateDirections( glm::quat rotation ) {
void Orientation::setRightUpFront( const glm::vec3 &r, const glm::vec3 &u, const glm::vec3 &f ) {
right = r;
up = u;
front = f;
quat = quat * rotation;
glm::mat4 rotationMatrix = glm::mat4_cast(quat);
right = glm::vec3( glm::vec4( IDENTITY_RIGHT, 0.0f ) * rotationMatrix );
up = glm::vec3( glm::vec4( IDENTITY_UP, 0.0f ) * rotationMatrix );
front = glm::vec3( glm::vec4( IDENTITY_FRONT, 0.0f ) * rotationMatrix );
}
void Orientation::testForOrthogonalAndNormalizedVectors( float epsilon ) {
// XXXBHG - this test has not yet been reworked to match the correct vector orientation
// of the coordinate system
// bail for now, assume all is good
return;
// make sure vectors are normalized (or close enough to length 1.0)
float rightLength = glm::length( right );
float upLength = glm::length( up );
float frontLength = glm::length( front );
if (( rightLength > 1.0f + epsilon )
|| ( rightLength < 1.0f - epsilon )) {
printLog( "Error in Orientation class: right direction length is %f \n", rightLength );
}
assert ( rightLength > 1.0f - epsilon );
assert ( rightLength < 1.0f + epsilon );
if (( upLength > 1.0f + epsilon )
|| ( upLength < 1.0f - epsilon )) {
printLog( "Error in Orientation class: up direction length is %f \n", upLength );
}
assert ( upLength > 1.0f - epsilon );
assert ( upLength < 1.0f + epsilon );
if (( frontLength > 1.0f + epsilon )
|| ( frontLength < 1.0f - epsilon )) {
printLog( "Error in Orientation class: front direction length is %f \n", frontLength );
}
assert ( frontLength > 1.0f - epsilon );
assert ( frontLength < 1.0f + epsilon );
// make sure vectors are orthogonal (or close enough)
glm::vec3 rightCross = glm::cross( up, front );
glm::vec3 upCross = glm::cross( front, right );
glm::vec3 frontCross = glm::cross( right, up );
float rightDiff = glm::length( rightCross - right );
float upDiff = glm::length( upCross - up );
float frontDiff = glm::length( frontCross - front );
if ( rightDiff > epsilon ) {
printLog( "Error in Orientation class: right direction not orthogonal to up and/or front. " );
printLog( "The tested cross of up and front is off by %f \n", rightDiff );
}
assert ( rightDiff < epsilon );
if ( upDiff > epsilon ) {
printLog( "Error in Orientation class: up direction not orthogonal to front and/or right. " );
printLog( "The tested cross of front and right is off by %f \n", upDiff );
}
assert ( upDiff < epsilon );
if ( frontDiff > epsilon ) {
printLog( "Error in Orientation class: front direction not orthogonal to right and/or up. " );
printLog( "The tested cross of right and up is off by %f \n", frontDiff );
}
assert ( frontDiff < epsilon );
}

View file

@ -1,6 +1,5 @@
//-----------------------------------------------------------
//
// Created by Jeffrey Ventrella
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
//
//-----------------------------------------------------------
@ -8,52 +7,43 @@
#ifndef __interface__orientation__
#define __interface__orientation__
#include <cmath> // with this work? "Math.h"
#include <cmath>
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
enum Axis
{
ORIENTATION_RIGHT_AXIS,
ORIENTATION_UP_AXIS,
ORIENTATION_FRONT_AXIS
};
// this is where the coordinate system is represented
const glm::vec3 IDENTITY_RIGHT = glm::vec3( -1.0f, 0.0f, 0.0f );
const glm::vec3 IDENTITY_UP = glm::vec3( 0.0f, 1.0f, 0.0f );
const glm::vec3 IDENTITY_FRONT = glm::vec3( 0.0f, 0.0f, 1.0f );
class Orientation
{
public:
Orientation();
void set( Orientation );
void setToIdentity();
void yaw ( float );
void pitch( float );
void roll ( float );
const glm::vec3 & getRight() const { return right; }
const glm::vec3 & getUp () const { return up; }
const glm::vec3 & getFront() const { return front; }
const glm::vec3 & getIdentityRight() const { return IDENTITY_RIGHT; }
const glm::vec3 & getIdentityUp () const { return IDENTITY_UP; }
const glm::vec3 & getIdentityFront() const { return IDENTITY_FRONT; }
private:
float _yaw;
float _pitch;
float _roll;
glm::quat quat;
glm::vec3 right;
glm::vec3 up;
glm::vec3 front;
void update(); // actually updates the vectors from yaw, pitch, roll
public:
Orientation();
void yaw ( float );
void pitch ( float );
void roll ( float );
float getYaw() { return _yaw; };
float getPitch(){ return _pitch; };
float getRoll(){ return _roll; };
void set( Orientation );
void setToIdentity();
const glm::vec3& getRight() const { return right; }
const glm::vec3& getUp() const { return up; }
const glm::vec3& getFront() const { return front; }
void setRightUpFront( const glm::vec3 &, const glm::vec3 &, const glm::vec3 & );
private:
void testForOrthogonalAndNormalizedVectors( float epsilon );
void rotateAndGenerateDirections( glm::quat rotation );
};
#endif