From b388e9a760ed0218221b7a8cad43c5595d1b9276 Mon Sep 17 00:00:00 2001 From: Jeffrey Ventrella Date: Wed, 1 May 2013 13:00:08 -0700 Subject: [PATCH] (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 --- interface/src/Avatar.cpp | 95 ++++++------ interface/src/Avatar.h | 79 +++++----- interface/src/AvatarTouch.cpp | 31 +++- interface/src/AvatarTouch.h | 6 +- interface/src/Camera.cpp | 24 ++-- interface/src/Camera.h | 2 +- interface/src/main.cpp | 42 +++--- libraries/avatars/src/Orientation.cpp | 200 +++++++++----------------- libraries/avatars/src/Orientation.h | 64 ++++----- 9 files changed, 247 insertions(+), 296 deletions(-) diff --git a/interface/src/Avatar.cpp b/interface/src/Avatar.cpp index 21fa44e651..127efe1b2e 100644 --- a/interface/src/Avatar.cpp +++ b/interface/src/Avatar.cpp @@ -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) { diff --git a/interface/src/Avatar.h b/interface/src/Avatar.h index 0f252af378..4b0ca1042d 100644 --- a/interface/src/Avatar.h +++ b/interface/src/Avatar.h @@ -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(); diff --git a/interface/src/AvatarTouch.cpp b/interface/src/AvatarTouch.cpp index 41e040c382..d90077a2d8 100644 --- a/interface/src/AvatarTouch.cpp +++ b/interface/src/AvatarTouch.cpp @@ -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 #include "avatars_Log.h" -#include -#include -//#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 ); -} - - diff --git a/libraries/avatars/src/Orientation.h b/libraries/avatars/src/Orientation.h index 1b64230812..8441c182b8 100755 --- a/libraries/avatars/src/Orientation.h +++ b/libraries/avatars/src/Orientation.h @@ -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 // with this work? "Math.h" +#include #include +#include -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