Prendendo o mouse dentro da janela no OpenGL com GLUT?

8

Entendo perfeitamente que o GLUT é limitado e o seguinte problema provavelmente não pode ser resolvido com o OpenGL / GLUT, mas como não sei exatamente se pode ou não, é melhor perguntar. Talvez esteja fazendo algo errado ou esquecendo algo importante. Ou provavelmente não, e o GLUT não fica melhor que isso.

Meu problema é que não consigo prender o mouse dentro da janela. Bem, na verdade, eu posso, o código abaixo faz exatamente isso. Prendo o mouse dentro da janela e posso usá-lo livremente para girar o mundo. O problema? Se mover o mouse muito rápido, posso sair da prisão da janela.

Existe uma maneira de contornar isso com o OpenGL / GLUT ou a única opção é outra biblioteca ou fazer algumas chamadas diretamente para a API do Windows? Palavras suficientes, aqui está o meu código atual:

void processPassiveMouseMotion(int x, int y) {
    static int centerX = glutGet(GLUT_WINDOW_WIDTH) / 2;
    static int centerY = glutGet(GLUT_WINDOW_HEIGHT) / 2;

    CameraAngle.x = -1.0f * (y - centerY);
    CameraAngle.y = -1.0f * (x - centerX);

    if(CameraAngle.x != 0.0f || CameraAngle.y != 0.0f) {
        SceneCamera.Rotate(CameraAngle);
        glutPostRedisplay();

        glutWarpPointer(centerX, centerY);
    }
}

glutPassiveMotionFunc(processPassiveMouseMotion);
rfgamaral
fonte

Respostas:

7

Que eu saiba, isso é específico da API do Windows - essa funcionalidade nem existe em todas as plataformas. Se você quiser pesquisar no meu código, poderá encontrar uma implementação do Windows em funcionamento (LockMouseCursor é o ponto de entrada no módulo OS, ClipCursor é a função real do Windows que faz a captura, mas há algumas sutilezas em torno dessa função - não deve ser muito difícil de decifrar.)

Eu também tenho uma implementação Linux no X puro (novamente, comece com LockMouseCursor), mas nunca encontrei uma API OSX utilizável para isso. Se você precisar de um ou criar um, verifique minha pergunta sobre o Stackoverflow :)

ZorbaTHut
fonte
Obrigado, vou manter este post em mente como referência. Você está lidando com APIs do Windows como eu suspeitava ser a única boa maneira de conseguir isso, mas eu não queria ir por esse caminho. Não que eu não saiba como, porque faço como já fiz antes, mas pelo que estou fazendo, não vale a pena incomodar e não é uma prioridade.
Rfgamaral 23/03
2

Com uma pesquisa rápida nas especificações do GLUT , o GLUT parece não ter recursos de captura de mouse. O melhor que você pode fazer (como você parece estar fazendo) é deformar o cursor para o centro e esperar que o usuário não seja rápido o suficiente (ou não esteja usando um tablet) =)

Ou você pode mudar para SDL ou SFML , pois o GLUT foi projetado apenas para teste, não para software "real".

Jari Komppa
fonte
Embora eu concorde com o seu comentário em geral, quero insistir fortemente contra o SDL porque, oh cara, o SDL tem grandes problemas. SFML é ótimo, use isso!
ZorbaTHut
Ambos têm seus lados, e eu como SDL, assim .. =)
Jari Komppa
11
Por favor, não entenda errado, mas é a segunda vez que você está me dizendo para mudar. Embora eu aprecie a resposta de alguém, se eu insistir em postar perguntas específicas do GLUT, talvez eu tenha uma boa razão para isso e não consiga mudar? Eu já percebi como o GLUT é péssimo, mas eu tenho que aturar isso, não é minha escolha. Desculpe se pareço severo, mas odeio quando as pessoas insistem assim, "ouvi" você pela primeira vez.
Rfgamaral
Estou votando sua resposta porque estou ignorando o último parágrafo. :)
rfgamaral
2
Nazgulled, desculpe se pareço estar repetindo coisas, eu realmente não acompanho cujas perguntas estou respondendo =). Além disso, as pessoas acabam encontrando essa pergunta por meio de pesquisas, e eu também quero responder a elas, não apenas a você.
Jari Komppa
2

Experimente uma versão mais recente do freeglut; Meu v2.6, prende o cursor com glutWarpPointer sem nenhuma possibilidade de escapar pelo mouse.

Palax
fonte
1

No meu caso, modifique

glutWarpPointer(centerX, centerY);

para algo como

if (x != centerX || y != centerY) glutWarpPointer(centerX, centerY);

resolveu perfeitamente o problema.

O problema é causado pelo glutWarpPointer disparar outro evento de movimento passivo para (centerX, centerY), o que resulta em um loop e / ou inunda a fila de eventos. Para evitá-lo, basta verificar se o mouse está em (centerX, centerY); se estiver, não entorte.

Giumo
fonte