Estou escrevendo um jogo 2D em que meu mundo de jogo tem o eixo x rodando da esquerda para a direita, o eixo y rodando de cima para baixo e o eixo z fora da tela:
Enquanto meu mundo de jogo é de cima para baixo, o jogo é renderizado com uma leve inclinação:
Estou trabalhando em projetar do espaço do mundo para o espaço da tela e vice-versa. Eu tenho o primeiro trabalhando da seguinte maneira:
var viewport = new Viewport(0, 0, this.ScreenWidth, this.ScreenHeight);
var screenPoint = viewport.Project(worldPoint.NegateY(), this.ProjectionMatrix, this.ViewMatrix, this.WorldMatrix);
O NegateY()
método de extensão faz exatamente o que parece, pois o eixo y do XNA é executado de baixo para cima em vez de cima para baixo. A captura de tela acima mostra tudo funcionando. Basicamente, tenho vários pontos no espaço 3D que renderizo no espaço da tela. Posso modificar as propriedades da câmera em tempo real e vê-la animada para a nova posição. Obviamente, meu jogo atual usará sprites em vez de pontos e a posição da câmera será fixa, mas só estou tentando colocar toda a matemática no lugar antes de chegar a isso.
Agora, estou tentando converter de volta para o outro lado. Ou seja, dado um ponto x e y no espaço da tela acima, determine o ponto correspondente no espaço do mundo. Portanto, se eu apontar o cursor para, digamos, a parte inferior esquerda do trapézio verde, quero obter uma leitura do espaço mundial de (0, 480). A coordenada z é irrelevante. Ou melhor, a coordenada z sempre será zero ao mapear de volta para o espaço do mundo. Essencialmente, quero implementar esta assinatura de método:
public Vector2 ScreenPointToWorld(Vector2 point)
Eu tentei várias coisas para fazer isso funcionar, mas não estou tendo sorte. Meu último pensamento é que preciso ligar Viewport.Unproject
duas vezes com valores z próximos / distantes , calcular o resultante Ray
, normalizá-lo e calcular a interseção do Ray
com um Plane
que representa basicamente o nível do solo do meu mundo. No entanto, fiquei preso no último passo e não tinha certeza se estava complicando demais as coisas.
Alguém pode me indicar a direção certa de como conseguir isso?