Suponha que você esteja escrevendo um código de matriz que lida com rotação, tradução etc. para o espaço 3D.
Agora as matrizes de transformação precisam ser 4x4 para ajustar o componente de conversão.
No entanto, você realmente não precisa armazenar um w
componente no vetor, precisa ?
Mesmo na divisão de perspectiva, você pode simplesmente calcular e armazenar w
fora do vetor e dividir a perspectiva antes de retornar do método.
Por exemplo:
// post multiply vec2=matrix*vector
Vector operator*( const Matrix & a, const Vector& v )
{
Vector r ;
// do matrix mult
r.x = a._11*v.x + a._12*v.y ...
real w = a._41*v.x + a._42*v.y ...
// perspective divide
r /= w ;
return r ;
}
Existe um ponto em armazenar w
na classe Vector?
mathematics
vector
projection
bobobobo
fonte
fonte
r.x = ... + a._14*v.w;
r.y = ... + a._24*v.w;
r.z = ... + a._34*v.w;
r.w = ... + a._44*v.w;
Olhe para a minha resposta para mais detalhesRespostas:
Isenção de responsabilidade da edição : por conveniência nesta resposta, vetores com w == 0 são chamados vetores e com w == 1 são chamados pontos. Embora, como FxIII apontou, essa não seja uma terminologia matematicamente correta. No entanto, como o ponto da resposta não é a terminologia, mas a necessidade de distinguir os dois tipos de vetores, eu continuarei com isso. Por razões práticas, esta convenção é amplamente usada no desenvolvimento de jogos.
Não é possível distinguir entre vetores e pontos sem um componente 'w'. É 1 para pontos e 0 para vetores.
Se os vetores forem multiplicados por uma matriz de transformação afina 4x4 que tenha uma tradução em sua última linha / coluna, o vetor também será traduzido, o que está errado, apenas os pontos devem ser traduzidos. O zero no componente 'w' de um vetor cuida disso.
Destacar esta parte da multiplicação de vetores de matriz torna mais claro:
Ou seja, seria errado traduzir um vetor, por exemplo, um eixo de rotação, o resultado é simplesmente errado. Ao ter seu 4º componente zero, você ainda pode usar a mesma matriz que transforma os pontos para transformar o eixo de rotação e o resultado será válido. e seu comprimento é preservado desde que não exista escala na matriz. Esse é o comportamento que você deseja para vetores. Sem o 4º componente, você teria que criar 2 matrizes (ou 2 funções de multiplicação diferentes com um 4º parâmetro implícito) e fazer 2 chamadas de funções diferentes para pontos e vetores.
Para usar os registradores vetoriais de CPUs modernas (SSE, Altivec, SPUs), é necessário passar flutuações 4x de 32 bits de qualquer maneira (é um registrador de 128 bits), além de cuidar do alinhamento, geralmente 16 bytes. Portanto, você não tem a chance de proteger o espaço para o quarto componente.
EDIT: A resposta para a pergunta é basicamente
É preciso escolher um deles, não é possível armazenar apenas {x, y, z} e ainda usar apenas uma função de multiplicação de vetores matriciais. O XNA, por exemplo, usa a última abordagem, tendo 2 funções Transform em sua classe Vector3 , chamadas
Transform
eTransformNormal
Aqui está um exemplo de código que mostra as duas abordagens e demonstra a necessidade de distinguir os dois tipos de vetores em uma das duas maneiras possíveis. Vamos mover uma entidade do jogo com uma posição e uma direção de olhar no mundo, transformando-a em uma matriz. Se não usarmos o componente 'w', não poderemos mais usar a mesma multiplicação de vetores de matriz, como este exemplo demonstra. Se fizermos de qualquer maneira, obteremos uma resposta errada para o
look_dir
vetor transformado :Estado inicial da entidade:
Agora, uma transformação com uma translação de x + 5 e uma rotação de 90 graus em torno do eixo y será aplicada a essa entidade. A resposta correta após a transformação é:
Apenas obteremos a resposta correta se distinguirmos vetores com w == 0 e posições com w == 1 de uma das maneiras apresentadas acima.
fonte
Se você estiver criando uma classe Vector, presumo que a classe armazene a descrição de um vetor 3D. Os vetores 3D têm magnitudes x, ye z. Portanto, a menos que seu vetor precise de uma magnitude arbitrária, não, você não o armazenará na classe.
Há uma grande diferença entre um vetor e uma matriz de transformação. Como o DirectX e o OpenGL lidam com matrizes para você, normalmente não armazeno uma matriz 4x4 no meu código; em vez disso, armazeno rotações de Euler (ou Quaternions, se você quiser - que coincidentemente têm um componente aw) e tradução x, y, z. A tradução é um vetor, se você desejar, e a rotação também caberia tecnicamente em um vetor, onde cada componente armazenaria a quantidade de rotação em torno de seu eixo.
Se você quiser mergulhar um pouco mais na matemática de um vetor, um vetor euclidiano é apenas uma direção e uma magnitude. Então, tipicamente, isso é representado por um triplo de números, onde cada número é a magnitude ao longo de um eixo; sua direção está implícita pela combinação dessas três magnitudes, e a magnitude pode ser encontrada com a fórmula da distância euclidiana . Ou, às vezes, ele realmente é armazenado como uma direção (um vetor com comprimento = 1) e uma magnitude (uma flutuação), se é o que é conveniente (por exemplo, se a magnitude mudar com mais frequência do que a direção, pode ser mais conveniente apenas alterar esse número de magnitude do que pegar um vetor, normalizá-lo e multiplicar os componentes pela nova magnitude).
fonte
A quarta dimensão no vetor 3D é usada para calcular as transformações afins que serão impossíveis de calcular usando apenas matrizes. O espaço permanece tridimensional, então isso significa que o quarto é mapeado no espaço 3D de alguma forma.
Mapear uma dimensão significa que diferentes vetores 4D indicam o mesmo ponto 3D. O mapa é que, se A = [x ', y', z'.w '] e B = [x ", y", z ", w"], eles representam o mesmo ponto se x' / x "= y ' / y "= z '/ z" = w' / w "= α, isto é, o componente é proporcional para o mesmo coeficiente α.
Disse que você pode expressar um ponto - digamos (1,3,7) - de maneiras infinitas, como (1,3,7,1) ou (2,6,14,2) ou (131,393,917,131) ou em geral (α · 1, a · 3, a · 7, a).
Isso significa que você pode dimensionar um vetor 4D para outro representando o mesmo ponto 3D, para que w = 1: a forma (x, y, z, 1) seja a forma canônica.
Quando você aplica uma matriz a esse vetor, pode obter um vetor que não tenha w = 1, mas sempre é possível dimensionar os resultados para armazená-lo de forma canônica. Portanto, a resposta parece ser "você deve usar vetores 4D ao fazer contas, mas não armazene o quarto componente" .
Isso é verdade, mas há alguns pontos que você não pode colocar em forma canônica: pontos como (4,2,5,0). Esses pontos são especiais, representam pontos infinitos direcionados e podem ser normalizados para o vetor unitário de forma consistente: você pode ir com segurança ao infinito e retornar (mesmo duas vezes) sem ser Chuck Norris. Você obterá uma divisão miserável por zero se tentar forçar esses vetores de forma canônica.
Agora você sabe, então a escolha é sua!
fonte
Sim você faz. Sua transformação está incorreta para alguns tipos de vetor. Você pode ver isso na biblioteca matemática do D3DX - eles têm duas funções diferentes de multiplicação de vetores matriciais, uma para w = 0 e outra para w = 1.
fonte
Depende do que você deseja e precisa. :)
Eu armazená-lo-ia, porque é necessário para transformações e coisas do tipo (você não pode multiplicar um vetor 3 com uma matriz 4x4), embora se você sempre tiver apenas 1 de um, acho que poderia fingir.
fonte