2014-05-19 28 views
1

我希望将鼠标和键盘输入与Oculus Rift结合起来,为用户创造流畅的体验。目标是:将键盘/鼠标和其他来源准确地结合(?)Quaterions

  • 位置运动100%由键盘控制相对于人面对的方向。
  • 取向由Oculus Rift等HMD设备控制100%。
  • 鼠标轨道功能增加了使用Oculus Rift的人的方向。例如,如果我向左看,我仍然可以将鼠标移动到更“向左”移动。

现在,当有人没有Oculus Rift时我有100%的工作代码,我只是不知道如何将Oculus Rift的方向和其他元素结合到我已经工作的代码中以获得它100%。

无论如何,这里是控制无Oculus Rift以键盘和鼠标我的工作代码:

注意,所有这些代码都假定角度模式下,相机的:

/* 

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; 

的Oculus Rift通过他们的SDK提供定位数据,并可以像这样访问:

/* 

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); 

之后,最后一行t他glm基础quaterion“CurrentOrientation”有正确的信息,如果直接插入现有的MVP矩阵结构并发送到OpenGL将允许您在环境中移动头部而不会出现问题。

现在,我的问题是如何将这两部分成功结合在一起。

当我在过去完成此操作时,会导致旋转停留在原位(当您转动头部时左边继续向左旋转,而不是刚刚旋转的量)以及我无法更准确地确定人员面对的方向,以便我的位置控制工作。

所以在这一点上,因为我再也不能确定什么是“向前”我的位置控制基本上成为废话...

我怎样才能成功地实现自己的目标?

回答

1

我已经做了一些工作,通过维护代表玩家位置和方向的“相机”矩阵,然后在渲染过程中,使用从头戴式耳机收集的最新定向数据进行组合。

我有一个单一的interaction class,它旨在从各种来源(包括键盘和操纵杆(以及太空鼠或Razer Hydra))提取输入。

您可能会发现像我一样将状态维持为单个组合矩阵,而不是试图在每一帧中组成一个lookat矩阵。

如果你看看我的Rift.cpp基类来开发我的例子,你会看到我捕获键盘输入并将其积累在CameraControl实例中。这是在实例积累,使得applyInteraction通话过程以后,我们可以申请由键盘显示运动,与其他投入一起:

void RiftApp::onKey(int key, int scancode, int action, int mods) { 
    ... 
    // Allow the camera controller to intercept the input 
    if (CameraControl::instance().onKey(player, key, scancode, action, mods)) { 
    return; 
    } 
    ... 
} 

在我的每帧更新代码我查询任何其他功能的设备和应用所有矩阵的输入。然后,我与球员位置的倒数更新模型视图矩阵:

void RiftApp::update() { 
    ... 
    CameraControl::instance().applyInteraction(player); 
    gl::Stacks::modelview().top() = glm::inverse(player); 
    ... 
} 

最后,在我的渲染代码,我有以下的,它适用于耳机定位:

void RiftApp::draw() { 
    gl::MatrixStack & mv = gl::Stacks::modelview(); 
    gl::MatrixStack & pr = gl::Stacks::projection(); 
    for_each_eye([&](ovrEyeType eye) { 
    gl::Stacks::with_push(pr, mv, [&]{ 
     ovrPosef renderPose = ovrHmd_BeginEyeRender(hmd, eye); 
     // Set up the per-eye modelview matrix 
     { 
     // Apply the head pose 
     glm::mat4 m = Rift::fromOvr(renderPose); 
     mv.preMultiply(glm::inverse(m)); 
     // Apply the per-eye offset 
     glm::vec3 eyeOffset = Rift::fromOvr(erd.ViewAdjust); 
     mv.preMultiply(glm::translate(glm::mat4(), eyeOffset)); 
     } 

     // Render the scene to an offscreen buffer 
     frameBuffers[eye].activate(); 
     renderScene(); 
     frameBuffers[eye].deactivate(); 

     ovrHmd_EndEyeRender(hmd, eye, renderPose, &eyeTextures[eye].Texture); 
    }); 
    GL_CHECK_ERROR; 
    }); 
    ... 
} 
+0

谢谢你,我会给这个镜头。 – user3434662

+0

你的代码帮助我走向正确的方向;再次感谢。 – user3434662