Jump to content

  • Log In with Google      Sign In   
  • Create Account

Interested in a FREE copy of HTML5 game maker Construct 2?

We'll be giving away three Personal Edition licences in next Tuesday's GDNet Direct email newsletter!

Sign up from the right-hand sidebar on our homepage and read Tuesday's newsletter for details!


We're also offering banner ads on our site from just $5! 1. Details HERE. 2. GDNet+ Subscriptions HERE. 3. Ad upload HERE.


Combining(?) Quaterions Accurately from Keyboard/Mouse and other sources ...


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
1 reply to this topic

#1 tmason   Members   -  Reputation: 285

Like
0Likes
Like

Posted 18 May 2014 - 06:21 PM

Hello,

 

I would like to combine mouse and keyboard inputs with the Oculus Rift to create a smooth experience for the user. The goals are:

  • Positional movement 100% controlled by the keyboard relative to the direction the person is facing.
  • Orientation controlled 100% by HMD devices like the Oculus Rift.
  • Mouse orbit capabilities adding to the orientation of the person using the Oculus Rift. For example, if I am looking left I can still move my mouse to "move" more leftward.

Now, I have 100% working code for when someone doesn't have an Oculus Rift, I just don't know how to combine the orientation and other elements of the Oculus Rift to my already working code to get it 100%.

 

Not good on the math.

 

Anyway, here is my working code for controlling the keyboard and mouse without the Oculus Rift:

 

Note that all of this code assumes a perspective mode of the camera:

/*

Variables

*/

glm::vec3 DirectionOfWhereCameraIsFacing;
glm::vec3 CenterOfWhatIsBeingLookedAt;
glm::vec3 PositionOfEyesOfPerson;
glm::vec3 CameraAxis;
glm::vec3 DirectionOfUpForPerson;
glm::quat CameraQuatPitch;
float     Pitch;
float	  Yaw;
float	  Roll;
float     MouseDampingRate;
float     PhysicalMovementDampingRate;
glm::quat CameraQuatYaw;
glm::quat CameraQuatRoll;
glm::quat CameraQuatBothPitchAndYaw;
glm::vec3 CameraPositionDelta;

/*

Inside display update function.

*/

DirectionOfWhereCameraIsFacing = glm::normalize(CenterOfWhatIsBeingLookedAt - PositionOfEyesOfPerson);
CameraAxis = glm::cross(DirectionOfWhereCameraIsFacing, DirectionOfUpForPerson);
CameraQuatPitch = glm::angleAxis(Pitch, CameraAxis);
CameraQuatYaw = glm::angleAxis(Yaw, DirectionOfUpForPerson);
CameraQuatRoll = glm::angleAxis(Roll, CameraAxis);
CameraQuatBothPitchAndYaw = glm::cross(CameraQuatPitch, CameraQuatYaw);
CameraQuatBothPitchAndYaw = glm::normalize(CameraQuatBothPitchAndYaw);
DirectionOfWhereCameraIsFacing = glm::rotate(CameraQuatBothPitchAndYaw, DirectionOfWhereCameraIsFacing);
PositionOfEyesOfPerson += CameraPositionDelta;
CenterOfWhatIsBeingLookedAt = PositionOfEyesOfPerson + DirectionOfWhereCameraIsFacing * 1.0f;
Yaw *= MouseDampingRate;
Pitch *= MouseDampingRate;
CameraPositionDelta = CameraPositionDelta * PhysicalMovementDampingRate;
View = glm::lookAt(PositionOfEyesOfPerson, CenterOfWhatIsBeingLookedAt, DirectionOfUpForPerson);
ProjectionViewMatrix = Projection * View;

The Oculus Rift provides orientation data via their SDK and can be accessed like so:

/*

Variables

*/

ovrMatrix4f OculusRiftProjection;
glm::mat4	Projection;
OVR::Quatf	OculusRiftOrientation;
glm::quat	CurrentOrientation;

/*

Partial Code for retrieving projection and orientation data from Oculus SDK

*/

OculusRiftProjection = ovrMatrix4f_Projection(MainEyeRenderDesc[l_Eye].Desc.Fov, 10.0f, 6000.0f, true);

for (int o = 0; o < 4; o++){
	for (int i = 0; i < 4; i++) {
		Projection[o][i] = OculusRiftProjection.M[o][i];
	}
}

Projection = glm::transpose(Projection);

OculusRiftOrientation = PredictedPose.Orientation.Conj();

CurrentOrientation.w = OculusRiftOrientation.w;
CurrentOrientation.x = OculusRiftOrientation.x;
CurrentOrientation.y = OculusRiftOrientation.y;
CurrentOrientation.z = OculusRiftOrientation.z;

CurrentOrientation = glm::normalize(CurrentOrientation);

After that last line the glm based quaterion "CurrentOrientation" has the correct information which, if plugged straight into the MVP matrix and sent into OpenGL will allow you to move your head around in the environment without issue.

 

Now, my problem is how to combine the two parts together successfully.

 

When I have done this in the past it results in the rotation stuck in place (when you turn your head left you keep rotating left as opposed to just rotating in the amount that you turned) and the fact that I can no longer accurately determine the direction the person is facing so that my position controls work.

 

How can I successfully achieve my goals?

 

Thank you for your time and all of your help thus far.

 

Very much appreciated.


Edited by tmason, 18 May 2014 - 06:22 PM.


Sponsor:

#2 tmason   Members   -  Reputation: 285

Like
0Likes
Like

Posted 20 May 2014 - 12:52 PM

Hello to All,

So I completely resolved the problem down to a simple issue of getting the correct rotation.

I think a video explains it best: http://tinypic.com/player.php?v=nyi7g2%3E&s=8

The link takes you to a free video hosting service tinypic.com.

What happens is that rotating left or right is OK until after you go past approximately 75 degrees in which case the viewpoint goes crazy.

Additionally, looking upwards in the rift actually makes you look down and looking down makes you look up. It also rotates crazily after 75 degrees.

Any ideas? Thank you for your time.

Anyway, here is the new code:

/*
 
Variables
 
*/
 
glm::vec3 DirectionOfWhereCameraIsFacing;
glm::vec3 RiftDirectionOfWhereCameraIsFacing;
glm::vec3 CenterOfWhatIsBeingLookedAt;
glm::vec3 RiftCenterOfWhatIsBeingLookedAt;
glm::vec3 PositionOfEyesOfPerson;
glm::vec3 CameraAxis;
glm::vec3 DirectionOfUpForPerson;
glm::quat CameraQuatPitch;
float     Pitch;
float	  Yaw;
float	  Roll;
float     MouseDampingRate;
float     PhysicalMovementDampingRate;
glm::quat CameraQuatYaw;
glm::quat CameraQuatRoll;
glm::quat CameraQuatBothPitchAndYaw;
glm::vec3 CameraPositionDelta;
 
/*
 
Inside display update function.
 
*/
 
DirectionOfWhereCameraIsFacing = glm::normalize(CenterOfWhatIsBeingLookedAt - PositionOfEyesOfPerson);
CameraAxis = glm::cross(DirectionOfWhereCameraIsFacing, DirectionOfUpForPerson);
CameraQuatPitch = glm::angleAxis(CurrentCameraViewingSettings.Pitch, CameraAxis);
CameraQuatYaw = glm::angleAxis(CurrentCameraViewingSettings.Yaw, DirectionOfUpForPerson);
CameraQuatRoll = glm::angleAxis(CurrentCameraViewingSettings.Roll, CameraAxis);
CameraQuatBothPitchAndYaw = glm::cross(CameraQuatPitch, CameraQuatYaw);
CameraQuatBothPitchAndYaw = glm::normalize(CameraQuatBothPitchAndYaw);
DirectionOfWhereCameraIsFacing = glm::rotate(CameraQuatBothPitchAndYaw, DirectionOfWhereCameraIsFacing);
CameraUpdateMutex.lock();
RiftDirectionOfWhereCameraIsFacing = DirectionOfWhereCameraIsFacing;
RiftDirectionOfWhereCameraIsFacing = glm::rotate(CurrentOrientation, DirectionOfWhereCameraIsFacing);
CameraUpdateMutex.unlock();
PositionOfEyesOfPerson += CameraPositionDelta;
CenterOfWhatIsBeingLookedAt = PositionOfEyesOfPerson + DirectionOfWhereCameraIsFacing * 1.0f;
CameraUpdateMutex.lock();
RiftCenterOfWhatIsBeingLookedAt = PositionOfEyesOfPerson + RiftDirectionOfWhereCameraIsFacing * 1.0f;
CameraUpdateMutex.unlock();
CurrentCameraViewingSettings.Yaw *= CurrentCameraViewingSettings.MouseDampingRate;
CurrentCameraViewingSettings.Pitch *= CurrentCameraViewingSettings.MouseDampingRate;
CameraPositionDelta = CameraPositionDelta * CurrentCameraViewingSettings.PhysicalMovementDampingRate;
View = glm::lookAt(PositionOfEyesOfPerson, CenterOfWhatIsBeingLookedAt, DirectionOfUpForPerson);

And here is the updated code within the display function.

Again, partial listing:

/*
 
Variables
 
*/
 
ovrMatrix4f OculusRiftProjection;
glm::mat4	RiftProjection;
OVR::Quatf	OculusRiftOrientation;
glm::quat	CurrentOrientation;
glm::vec3	CurrentEulerAngles;
glm::mat4	RiftView;
glm::mat4	RiftProjectionViewMatrix;
 
/*
 
Partial Code for retrieving projection and orientation data from Oculus SDK
 
*/
 
ovrEyeType l_Eye = (*MainRiftDeviceDesc).EyeRenderOrder[l_EyeIndex];
ovrPosef l_EyePose = ovrHmd_BeginEyeRender((*MainRiftDevice), l_Eye);
OVR::Posef PredictedPose = ovrHmd_GetSensorState((*MainRiftDevice), m_HmdFrameTiming.ScanoutMidpointSeconds).Predicted.Pose;
 
glViewport(MainEyeRenderDesc[l_Eye].Desc.RenderViewport.Pos.x,
	MainEyeRenderDesc[l_Eye].Desc.RenderViewport.Pos.y,
	MainEyeRenderDesc[l_Eye].Desc.RenderViewport.Size.w,
	MainEyeRenderDesc[l_Eye].Desc.RenderViewport.Size.h);
 
OculusRiftProjection = ovrMatrix4f_Projection(MainEyeRenderDesc[l_Eye].Desc.Fov, 10.0f, 6000.0f, true);
 
for (int o = 0; o < 4; o++){
	for (int i = 0; i < 4; i++) {
		RiftProjection[o][i] = OculusRiftProjection.M[o][i];
	}
}
 
RiftProjection = glm::transpose(RiftProjection);
 
OculusRiftOrientation = PredictedPose.Orientation;
 
OculusRiftOrientation.GetEulerAngles<OVR::Axis_X, OVR::Axis_Y, OVR::Axis_Z, OVR::Rotate_CCW, OVR::Handed_R>
	(&CurrentEulerAngles.x, &CurrentEulerAngles.y, &CurrentEulerAngles.z);
 
CurrentOrientation = glm::quat(CurrentEulerAngles);
 
RiftView = glm::lookAt(PositionOfEyesOfPerson, RiftCenterOfWhatIsBeingLookedAt, DirectionOfUpForPerson);
RiftView = glm::translate(RiftView, glm::vec3(l_EyePose.Position.x, l_EyePose.Position.y, l_EyePose.Position.z));
RiftProjectionViewMatrix = RiftProjection * RiftView;





Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS