Three.js: unproject - ¿Cómo obtener la posición real en la 'pantalla (arriba, izquierda)' de un objeto 3D específico?

Creado en 4 ene. 2011  ·  21Comentarios  ·  Fuente: mrdoob/three.js

Con ejemplos, sabía que había alguna forma de proyectar un punto en la pantalla (x, y) a los puntos de '3d'. Pero no sé cómo traducirlo. Gracias por cualquier pista.

Question

Comentario más útil

En caso de que alguien todavía necesite esto después de actualizar ...

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 comentarios

Probablemente usando el proyector, pero MrDoob obviamente sabe más sobre esto :)

Uhm, ¿quizás deberíamos tener un object3d.screen que sería un Vector2 y actualizarlo en cada render?

Si ese object3D.screen Vector solo se usa para traducir la object3D.position de cada object3D a 2D, ¿object3D.screen no sería de muy poco valor? Quiero decir: creo que sería más útil poder trasladar cualquier punto x, y, z de cualquier malla en la posición x, y, z a coordenadas 2D.

Eso, a su vez, significa que nunca sería posible calcular previamente cada posición 3D de cada objeto.

En mi humilde opinión, sería útil tener, por ejemplo, una función THREE.3dto2d() que tome un Vector3 (que representa un punto en la escena) o un Vector3 y un objeto (donde el Vector3 representa un punto en el objeto).
Luego, la función calcula la posición 3D en la escena.
Por último, toma la cámara, su posición, rotación, la matriz de proyección, etc., y vuelve a traducir el punto a 2D.

Supongo que la cámara también debería ser un parámetro de la función ...

Bueno ... Projector.projectScene ya hace eso;)

Mira, sabía que era el Proyector ... ;-)

¿Hay algún ejemplo que lo use?

Hmm ... todavía no ... esas funciones están diseñadas para ser utilizadas con el Renderer ... devuelven una lista de elementos para renderizar sin relación con los objetos originales. Tal vez debería poner un enlace a los objetos originales y eso servirá ... Hmmm, necesito pensar un poco más.

Actualmente estoy de vacaciones, pero haré una demostración de destello de lente (o algo) tan pronto como regrese (la semana que viene).

Seguro, disfruta de tus vacaciones y espero con ansias la nueva demostración. :-)

Hmm, esto solía funcionar para mí (r32), ya no en 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 después de projScreenMat.multiplyVector3(pos); solía tener un límite entre -1 y 1 ((0,0) en el centro de la vista.), pero ahora parece variar inesperadamente.

Sí, camera.matrix debe reemplazarse ahora con camera.matrixWorldInverse .
Prueba con esto:

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 };

}

Sí, eso funcionó, no sabía sobre los cambios de matrices. Espero que esta función de proyección responda a la pregunta de alivedise.

Creo que es el hilo adecuado para hacer mi pregunta sobre 3D Cube. Tengo un cubo dibujado en lienzo con caras en las que se puede hacer clic. El cubo gira libremente sobre el eje X y el eje Y. Lo que quiero es sacar la mayor parte de la cara frontal cuando el usuario suelte el mouse y hacerlo completamente visible girando automáticamente. Cualquier ayuda en este contexto sería muy agradecida.

Gracias.

@ imrantariq2011 : Eso no está realmente relacionado con este tema, ¿te importaría abrir uno nuevo? Gracias.

Para propósitos de mapeo de texturas, me gustaría poder obtener las coordenadas de pantalla x, y para cada vértice de una cara determinada.

Puedo ver cómo se puede hacer esto usando lo anterior (toScreenXY: function), pero primero se requieren los vértices transformados (escalados, traducidos y rotados) del mundo para una cara determinada. Pasé algún tiempo mirando Projector.projectScene y me pregunto si hay una forma más sencilla de lograr el objetivo anterior y parece que object.matrixWorld.getPosition () podría obtener el centroide del objeto en lugar de los vértices de la cara.

Sí, el código anterior era para uno de. Si necesita proyectar muchos puntos, lo mejor es extraer los bits de código de .projectScene() .

las personas que llegan hasta aquí pueden querer saber sobre esto:

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

Yo uso esto, funciona:

función toScreenXY (pos3D)
{
var proyector = nuevo THREE.Projector ();
var v = projector.projectVector (pos3D, cámara);
var percX = (vx + 1) / 2;
var percY = (-vy + 1) / 2;
var left = percX * window.innerWidth;
var top = percY * window.innerHeight;

return new THREE.Vector2 (izquierda, arriba);
}

El viernes 1 de agosto de 2014 a las 11:24 a.m., Artem Fitiskin [email protected] escribió:

Cuando uso toScreenXY, obtengo valores muy grandes.
console.log (pos): // x: -1474.1436403989792, y: -730.829023361206, z: 3.0004000663757324
y después de multiplicarlo con jqdiv, la función devuelve x e y muy grandes.
¿Qué estoy haciendo mal?
-
Responda a este correo electrónico directamente o véalo en GitHub.

@arieljake

Como se indica en las pautas , las solicitudes de ayuda deben dirigirse a stackoverflow . Esta placa es para errores y solicitudes de funciones.

bien ... sin embargo, el propio señor doob puso código, entonces, ¿qué pasa?

@arieljake # 1979

En caso de que alguien todavía necesite esto después de actualizar ...

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 muy antiguo, pero tenía un objeto anidado, que no funcionaba con el código anterior.
Mi caso fue: quería la posición x-e-y (y z) real para un objeto anidado después de la renderización, así que adapté los ejemplos anteriores.
Tenga en cuenta:

  1. Ahora proporciona el objeto completo como argumento en lugar de solo la posición del objeto en los ejemplos anteriores.
  2. Además, esto solo funcionará después de que el renderizador haya hecho su trabajo y llamado
  3. También funciona para objetos no anidados, pero hará algunos cálculos de más.
  4. También le proporciona una pantalla Z, que se puede utilizar para clasificar domElements o etiquetas zSort.
    El relativo de pantalla-z está entre 0 y 1, en relación con los planos de recorte frontal y posterior de la cámara / renderizador y esto funciona bien para mis propósitos (clasificación).
  5. Puede obtener el ancho y alto actuales de los renderizadores mediante renderer.domElement.width y renderer.domElement.height.
scene.updateMatrixWorld(); 

y

parent.updateMatrixWorld(); 

`` js
función nestedObjecttoScreenXYZ (obj, cámara, ancho, alto)
{
vector var = nuevo TRES.Vector3 ();
vector.setFromMatrixPosition (obj.matrixWorld);
var widthHalf = (ancho / 2);
var heightHalf = (altura / 2);
vector.project (cámara);
vector.x = (vector.x * widthHalf) + widthHalf;
vector.y = - (vector.y * heightHalf) + heightHalf;
vector de retorno;
};



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

En caso de que alguien se encuentre con el mismo problema.

¿Fue útil esta página
0 / 5 - 0 calificaciones