Three.js: desprojetar - Como obter a posição real na 'tela (superior, esquerda)' de um objeto 3d específico?

Criado em 4 jan. 2011  ·  21Comentários  ·  Fonte: mrdoob/three.js

Com base em exemplos, eu sabia que havia uma maneira de projetar um ponto na tela (x, y) para os pontos de '3d'. Mas não consigo descobrir como traduzi-lo de volta. Obrigado por qualquer pista.

Question

Comentários muito úteis

Caso alguém ainda precise disso após a atualização ...

function screenXY(obj){

  var vector = obj.clone();
  var windowWidth = window.innerWidth;
  var minWidth = 1280;

  if(windowWidth < minWidth) {
    windowWidth = minWidth;
  }

  var widthHalf = (windowWidth/2);
  var heightHalf = (window.innerHeight/2);

  vector.project(camera);

  vector.x = ( vector.x * widthHalf ) + widthHalf;
  vector.y = - ( vector.y * heightHalf ) + heightHalf;
  vector.z = 0;

  return vector;

};

Todos 21 comentários

Provavelmente usando o projetor, mas MrDoob obviamente sabe mais sobre isso :)

Uhm, talvez devêssemos ter um object3d.screen que seria um Vector2 e atualizá-lo em cada render?

Se esse vetor object3D.screen for usado apenas para converter o object3D.position de cada object3D para 2D, então object3D.screen não teria muito pouco valor? Quer dizer: acho que seria mais útil ser capaz de traduzir qualquer ponto x, y, z de qualquer malha na posição x, y, z para coordenadas 2D.

Isso, por sua vez, significa que nunca seria possível pré-calcular todas as posições 3D de todos os objetos.

Seria útil ter, por exemplo, uma função THREE.3dto2d() que receba um Vector3 (representando um ponto na cena) ou um Vector3 e um objeto (onde o Vector3 representa um ponto no objeto).
A função então calcula a posição 3D na cena.
Por fim, ele pega a câmera, sua posição, rotação, a projectionMatrix etc, e traduz o ponto de volta para 2D.

Acho que a câmera deve ser um parâmetro da função também ...

Bem ... Projector.projectScene kinda já faz isso;)

Veja, eu sabia que era o projetor ... ;-)

Existe um exemplo usando isso?

Hmm ... ainda não ... essas funções são projetadas para serem usadas com o Renderer ... elas retornam uma lista de elementos para renderizar sem relação com os objetos originais. Talvez eu deva apenas colocar algum link para os objetos originais e isso basta ... Hmmm, preciso pensar um pouco mais.

No momento, estou de férias, mas farei uma demonstração do lens flare (ou algo assim) assim que voltar (semana que vem).

Com certeza, aproveite as suas férias e estou ansioso pela nova demonstração! :-)

Hmm, isso costumava funcionar para mim (r32), não funciona mais no r35 ..

  toScreenXY: function(position, camera, jqdiv) {
    // converts 3D position to screen coords
    var pos = position.clone();
    projScreenMat = new THREE.Matrix4();
    projScreenMat.multiply( camera.projectionMatrix, camera.matrix);
    projScreenMat.multiplyVector3(pos);
    return { x: (pos.x+1)*jqdiv.width()/2 + jqdiv.offset().left, 
             y:(-pos.y+1)*jqdiv.height()/2 +jqdiv.offset().top }; 
  },

pos após projScreenMat.multiplyVector3(pos); costumava ser limitado entre -1 e 1 ((0,0) no centro da visão.), mas agora parece variar inesperadamente ..

Sim, camera.matrix precisa ser substituído agora por camera.matrixWorldInverse .
Experimente com isto:

toScreenXY: function ( position, camera, jqdiv ) {

    var pos = position.clone();
    projScreenMat = new THREE.Matrix4();
    projScreenMat.multiply( camera.projectionMatrix, camera.matrixWorldInverse );
    projScreenMat.multiplyVector3( pos );

    return { x: ( pos.x + 1 ) * jqdiv.width() / 2 + jqdiv.offset().left,
         y: ( - pos.y + 1) * jqdiv.height() / 2 + jqdiv.offset().top };

}

Sim, funcionou, não sabia sobre as mudanças de matrizes. Espero que esta função de projeção tenha respondido à pergunta de alivedise.

Acho que é o tópico certo para fazer minha pergunta sobre o Cubo 3D. Tenho um cubo desenhado na tela com faces clicáveis. O cubo está girando livremente no eixo X e eixo Y. O que eu quero é obter o máximo da face frontal quando o usuário soltar o mouse e torná-la totalmente visível ao girar automaticamente. Qualquer ajuda neste contexto seria muito grata.

Obrigado.

@ imrantariq2011 : Isso não está realmente relacionado a esse problema, você se importaria de abrir um novo? Obrigado.

Para fins de mapeamento de textura, gostaria de poder obter as coordenadas de tela x, y para cada vértice de uma determinada face.

Eu posso ver como isso poderia ser feito usando o acima (toScreenXY: função) - mas primeiro os vértices transformados (dimensionados, traduzidos e girados) do mundo para uma determinada face são necessários. Passei algum tempo olhando para Projector.projectScene e me pergunto se há uma maneira mais simples de atingir o objetivo acima e parece que object.matrixWorld.getPosition () pode obter o centróide do objeto em vez dos vértices da face.

Sim, o código acima era para um de. Se você precisar projetar muitos pontos, é melhor extrair os bits do código do próprio .projectScene() .

as pessoas que chegam aqui podem querer saber sobre isso:

https://github.com/zachberry/threejs-tracking-3d-to-2d

Eu uso isso, funciona:

função toScreenXY (pos3D)
{
projetor var = novo TRÊS.Projetor ();
var v = projector.projectVector (pos3D, câmera);
var percX = (vx + 1) / 2;
var percY = (-vy + 1) / 2;
var left = percX * window.innerWidth;
var top = percY * window.innerHeight;

retornar novo TRÊS.Vetor2 (esquerda, topo);
}

Na sexta-feira, 1 de agosto de 2014 11h24, Artem Fitiskin [email protected] escreveu:

Quando eu uso toScreenXY, obtenho valores muito grandes.
console.log (pos): // x: -1474.1436403989792, y: -730.829023361206, z: 3.0004000663757324
e depois de multiplicá-lo por jqdiv, a função retorna x e y muito grandes.
O que estou fazendo de errado?
-
Responda a este e-mail diretamente ou visualize-o no GitHub.

@arieljake

Conforme declarado nas diretrizes , as solicitações de ajuda devem ser direcionadas para stackoverflow . Esta placa é para bugs e solicitações de recursos.

bem ... ainda o próprio sr. doob colocou código, então o que acontece?

@arieljake # 1979

Caso alguém ainda precise disso após a atualização ...

function screenXY(obj){

  var vector = obj.clone();
  var windowWidth = window.innerWidth;
  var minWidth = 1280;

  if(windowWidth < minWidth) {
    windowWidth = minWidth;
  }

  var widthHalf = (windowWidth/2);
  var heightHalf = (window.innerHeight/2);

  vector.project(camera);

  vector.x = ( vector.x * widthHalf ) + widthHalf;
  vector.y = - ( vector.y * heightHalf ) + heightHalf;
  vector.z = 0;

  return vector;

};

Ok, problema muito antigo, mas eu tinha um objeto aninhado que não funcionava com o código acima.
Meu caso era: eu queria a posição real xey (e z) para um objeto aninhado após a renderização, então adaptei os exemplos acima.
Observe:

  1. Você agora fornece todo o objeto como um argumento, em vez de apenas o objeto.posição nos exemplos acima.
  2. Além disso, isso só funcionará depois que o renderizador tiver feito seu trabalho e chamado
  3. Também funciona para objetos não aninhados, mas fará alguns cálculos a mais.
  4. Ele também fornece uma tela-Z, que pode ser usada para classificar domElements ou rótulos zSort.
    O relativo screen-z está entre 0 e 1, em relação aos planos de recorte frontal e traseiro da câmera / renderizador e isso funciona bem para os meus objetivos (classificação).
  5. Você pode obter a largura e altura atuais dos renderizadores por renderer.domElement.width e renderer.domElement.height.
scene.updateMatrixWorld(); 

e

parent.updateMatrixWorld(); 

`` `js
função nestedObjecttoScreenXYZ (obj, câmera, largura, altura)
{
vetor var = novo TRÊS.Vetor3 ();
vector.setFromMatrixPosition (obj.matrixWorld);
var widthHalf = (largura / 2);
var heightHalf = (altura / 2);
vector.project (câmera);
vector.x = (vector.x * widthHalf) + widthHalf;
vector.y = - (vector.y * heightHalf) + heightHalf;
vetor de retorno;
};



typical call:
```js
var screenpos=NestedObjecttoScreenXY(object,camera,renderer.domElement.width,renderer.domElement.height,true);

Apenas no caso de alguém ter o mesmo problema.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

jack-jun picture jack-jun  ·  3Comentários

clawconduce picture clawconduce  ·  3Comentários

seep picture seep  ·  3Comentários

Horray picture Horray  ·  3Comentários

makc picture makc  ·  3Comentários