【问题标题】:OpenGL Camera - Move the camera without it snapping back when using SetCursorPos(x,y);?OpenGL 相机 - 使用 SetCursorPos(x,y); 时移动相机而不回弹?
【发布时间】:2012-05-07 20:31:06
【问题描述】:

我在尝试更新相机时遇到问题。

我想通过鼠标改变相机的俯仰和偏航(它在哪里看) 但我希望鼠标保持在窗口的中心。

//where MouseP.x .y is the mouse position 
//(which is centered to the current window)

//get old position of the mouse
OldP.x = MouseP.x;
OldP.y = MouseP.y;

//work out the distance traveled
Delta.x = MouseP.x - OldP.x;
Delta.y = MouseP.y - OldP.y;

//update the camera(using  distance traveled)
Rot.Yaw -=Delta.x/5;
Rot.Pitch -= Delta.y/5;

//move mouse to the center of the screen
SetCursorPos(CENTER_SCREEN_X,CENTER_SCREEN_Y);

问题是当鼠标设置为返回原点时,相机会快速返回到某个点。

我想通过从原点行进的距离而不是返回原点的距离来更新相机。

如果我把它拿出来,它会很好地工作,但当时的鼠标会跳出窗口。

【问题讨论】:

    标签: c++ opengl camera mousemove glulookat


    【解决方案1】:

    必须小心光标和 3D 鼠标移动。人们倾向于认为它是相关的,但实际上并非如此。 从 msdn 阅读文章: http://msdn.microsoft.com/en-us/library/windows/desktop/ee418864%28v=vs.85%29.aspx 《利用高清鼠标移动》 这就是在 3D 应用程序中必须获得鼠标输入的方式。 光标应该被隐藏了。

    如果您尝试将其重新居中,则会产生一种可怕的锯齿状感觉,其中光标试图在用户移动鼠标时逃离中心,但被一个看不见的弹簧保持在原位。这看起来不是很专业。您无法抗拒,因为您的应用程序未在鼠标光标显示之前安排。

    【讨论】:

      【解决方案2】:

      我认为这里的问题是您的代码块可能在WM_MOUSEMOVE 事件的捕获中?

      当您调用SetCursorPos 时,它本身会生成另一个WM_MOUSEMOVE 事件,因此您在移动鼠标时处理此代码块一次,当您调用SetCursorPos 时再处理一次,它的作用与此相反。

      您可能不想将SetCursorPos 放在 WM_MOUSEMOVE 事件捕获中,否则您将生成无限循环的消息(每个 SetCursorPos 都会生成另一个消息)。

      也许您可以将此代码移到消息泵之外,并在更新循环中每帧运行一次:查询当前鼠标位置,进行相机变换,然后将光标设置回原点。

      【讨论】:

      • 啊抱歉,我没有提到它不在 WM_MOUSEMOVE 事件中,正如你所说的,它在每一帧都被调用。我已经在不同的位置尝试过,但似乎问题出在函数内。
      • 你认为是否有可能将其溢出到线程中并放置一个互斥锁或信号量以仅在它返回到原点时发出更新信号?
      【解决方案3】:
      if(g_States::Instance().MouseLook())
      {
          //Test the mouse input
          POINT mousePos;
          GetCursorPos(&mousePos);
      
          mouseX = mousePos.x; //g_InputEngine::Instance().GetX();
          mouseY = mousePos.y; //g_InputEngine::Instance().GetY();
      
          mouseX = mouseX - m_HalfWidth;
          mouseY = mouseY - m_HalfHeight;
      
          mouseFloat = mouseX * C_MOUSESMOOTHINGFACTOR;
          g_Scene::Instance().GetCamera()->RotateYaw(-mouseFloat);
      
          mouseFloat = mouseY * C_MOUSESMOOTHINGFACTOR;
          g_Scene::Instance().GetCamera()->RotatePitch(mouseFloat);
      
          //Reset mouse to center on the screen
          SetCursorPos(m_HalfWidth,m_HalfHeight);
      }
      

      所以这是我之前为了好玩而开发的太空游戏原型的 Mouselook 功能,我所做的是将它改为使用 GetCursorPos(&mousePos);。无论您的输入代码何时更新鼠标光标位置,这都会获取光标的当前位置。该函数中的其余数学仅用于灵敏度和实际旋转相机。希望这段代码对您的工作有所帮助。

      如果您需要更多解释,请告诉我。

      编辑:我只记得我这样做的原因。这是因为屏幕闪烁它会移动,但是输入引擎会被SetCursorPos() 调用更新,因为我正在使用 WM_MOUSEMOVE 来更新输入引擎。我不确定您是如何获得您的意见的,但这应该仍然对您有所帮助。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-06-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多