Estou tentando criar um editor de jogos, atualmente apenas colocando diferentes tipos de formas e tal. Estou fazendo isso no Windows Forms enquanto desenha o 3D com o XNA. Portanto, se eu tiver algumas Formas na tela e clicar na tela, quero poder identificar "em qual" desses objetos você clicou.
Qual é o melhor método para isso? Como ter dois objetos um atrás do outro, ele deve ser capaz de reconhecer o que está na frente e não o que está atrás e também se eu girar a câmera e clicar no objeto por trás dela - ele deve identificá-lo e não o primeiro.
Existem maneiras inteligentes de fazer isso?
xna
c#
editors
map-editor
windows-forms
Deukalion
fonte
fonte
Respostas:
Neste vídeo, mostro como fazê-lo com código ... a projeção / exibição é isométrica, mas todos os cálculos são feitos em 3D ...
http://www.youtube.com/watch?v=axHp1f3RlHM
Quando calculo o raio do mouse, verifico a colisão em um avião ... mas o procedimento é analógico para verificar uma lista de esferas delimitadoras associadas aos seus objetos.
O algoritmo deve ser semelhante a este:
fonte
A primeira coisa que você precisa entender é transformar pontos 3D em coordenadas de tela 2D e vice-versa. Aqui estão algumas respostas que eu dei sobre esse assunto; Entendendo 3D para tela , 3D para 2D .
Agora, para ir da coordenada do mouse em 2D para 3D, você precisa fazer uma transformação 3D em 2D para trás. Isto é bastante simples.
Uma coordenada objeto / local é transformada no espaço da tela multiplicando-a pela matriz mundial (obtenha a coordenada mundial), depois pela matriz de visualização (faça a coordenada mundial em relação à câmera) e depois pela matriz de projeção (obtenha a coordenada da tela) .
Fazer isso de trás para frente é fácil. Inverta todas as matrizes. Em seguida, multiplique pela projeção invertida e pela matriz de vista invertida. Agora, você não terá uma coordenada 3D para o mouse. O motivo é que estava faltando uma dimensão de dados. Então, o que você tem é um raio. Mas isso é bom. O raio terá uma coordenada de definição e será apontado na mesma direção que a câmera olha para o vetor. Você também pode perceber que não precisa inverter a matriz mundial de nenhum objeto. Isso é apenas porque você realmente não quer o raio no objeto / espaço local, não faz sentido, você provavelmente também tem seus volumes de colisão definidos no espaço do mundo.
Agora tudo o que você precisa fazer é o teste de interseção círculo / caixa / raio poli para descobrir se o raio se cruza com um objeto.
Encontre todos os objetos que estão cruzados e mantenha uma lista. Em seguida, calcule a distância de cada objeto da câmera. O mais próximo da câmera é aquele que o usuário deseja escolher.
Aqui está o código que você precisaria fazer isso no XNA. Essa solução também deve funcionar para outros tipos de projetos (desde que você a converta primeiro). Se você está renderizando apenas sprites 2D, provavelmente não está usando uma matriz de projeção, então entregue a função Matrix.Identity.
fonte
Normalmente, criarei um volume delimitador do mouse. A origem é onde eu cliquei. Em seguida, conclua um teste de interseção fazendo um loop em todos os objetos. Em seguida, classifique a lista que você voltar com base nos critérios desejados e selecione o elemento 0.
fonte
Uma ideia que considerei, mas ainda não tentei:
Desenhe uma imagem fora da tela igual à imagem real, mas sem texturas etc. Simplesmente desenhe seus objetos, cada objeto em uma "cor" diferente, onde a "cor" é realmente apenas um número de objeto. Para descobrir o que há sob o mouse, basta olhar para a cor do pixel na imagem alternativa.
É claro que isso está desperdiçando muito trabalho, mas é a GPU e não a CPU, e com certeza resolverá as coisas exatamente pelas mesmas regras.
fonte