2014-05-19 50 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