Three.js: Unoject - Comment obtenir la position réelle sur «l'écran (en haut, à gauche)» d'un objet 3D spécifique?

Créé le 4 janv. 2011  ·  21Commentaires  ·  Source: mrdoob/three.js

Sur les exemples, je savais qu'il y avait un moyen de projeter un point sur l'écran (x, y) aux points de «3d». Mais je ne sais pas comment le traduire. Merci pour tout indice.

Question

Commentaire le plus utile

Incase quiconque en a encore besoin après la mise à niveau ...

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;

};

Tous les 21 commentaires

Utilisant probablement le projecteur, mais MrDoob en sait évidemment plus à ce sujet :)

Euh, peut-être devrions-nous avoir un object3d.screen qui serait un Vector2 et le mettre à jour à chaque rendu?

Si ce vecteur object3D.screen n'est utilisé que pour traduire la position object3D. de chaque object3D en 2D, alors object3D.screen n'aurait-il pas trop peu de valeur? Je veux dire: je pense qu'il serait plus utile de pouvoir traduire n'importe quel point x, y, z de n'importe quel maillage à la position x, y, z en coordonnées 2D.

Cela signifie à son tour qu'il ne sera jamais possible de précalculer chaque position 3D de chaque objet.

Il serait utile d'avoir par exemple une fonction THREE.3dto2d() qui prend soit un Vector3 (représentant un point dans la scène) soit un Vector3 et un objet (où le Vector3 représente un point sur l'objet).
La fonction calcule ensuite la position 3D dans la scène.
Enfin, il prend la caméra, sa position, sa rotation, la projectionMatrix, etc., et traduit le point en 2D.

Je suppose que la caméra devrait également être un paramètre de la fonction ...

Eh bien ... Projector.projectScene fait déjà un peu;)

Tu vois, je savais que c'était le projecteur ... ;-)

Y a-t-il un exemple qui l'utilise?

Hmm ... pas encore ... ces fonctions sont conçues pour être utilisées avec le Renderer ... elles renvoient une liste d'éléments à rendre sans relation avec les objets d'origine. Peut-être que je devrais juste mettre un lien vers les objets originaux et cela fera ... Hmmm, je dois y réfléchir un peu plus.

Je suis actuellement en vacances, mais je ferai une démo de lens flare (ou quelque chose) dès mon retour (la semaine prochaine).

Bien sûr, profitez de vos vacances et j'ai hâte de voir la nouvelle démo! :-)

Hmm, cela fonctionnait pour moi (r32), ce n'est plus le cas 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 après projScreenMat.multiplyVector3(pos); était plafonné entre -1 et 1 ((0,0) au centre de la vue.), mais semble maintenant varier de manière inattendue ..

Ouais, camera.matrix doit être remplacé maintenant par camera.matrixWorldInverse .
Essayez avec ceci:

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

}

Oui, cela a fonctionné, je ne savais pas sur les changements de matrices. J'espère que cette fonction de projection a répondu à la question d'Alivedise.

Je pense que c'est le bon fil pour poser ma question concernant 3D Cube. J'ai un cube dessiné sur une toile avec des faces cliquables. Le cube tourne librement sur l'axe X et l'axe Y. Ce que je veux, c'est tirer le meilleur parti de la face avant lorsque l'utilisateur relâche la souris et la rendre pleinement visible en la faisant pivoter automatiquement. Toute aide dans ce contexte serait très appréciée.

Je vous remercie.

@ imrantariq2011 : Ce n'est pas vraiment lié à ce problème, cela vous dérange-t-il d'en ouvrir un nouveau? Merci.

À des fins de mappage de texture, j'aimerais pouvoir obtenir les coordonnées d'écran x, y pour chaque sommet pour une face donnée.

Je peux voir comment cela pourrait être fait en utilisant ce qui précède (toScreenXY: function) - mais d'abord, le monde transformé (mis à l'échelle, traduit et pivoté) pour une face donnée est nécessaire. J'ai passé du temps à regarder Projector.projectScene et je me demande s'il existe un moyen plus simple d'atteindre l'objectif ci-dessus et il semble que object.matrixWorld.getPosition () pourrait obtenir le centre de gravité de l'objet plutôt que les sommets de la face.

Ouais, le code ci-dessus était pour l'un des. Si vous avez besoin de projeter de nombreux points, il est préférable d'extraire les bits de code de .projectScene() lui-même.

les gens qui arrivent ici voudront peut-être en savoir plus:

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

J'utilise ça, ça marche:

fonction toScreenXY (pos3D)
{
projecteur var = nouveau THREE.Projector ();
var v = projecteur.projectVector (pos3D, caméra);
var percX = (vx + 1) / 2;
var percY = (-vy + 1) / 2;
var gauche = percX * window.innerWidth;
var top = percY * window.innerHeight;

retourne le nouveau THREE.Vector2 (gauche, haut);
}

Le vendredi 1er août 2014 à 11h24, Artem Fitiskin [email protected] a écrit:

Quand j'utilise toScreenXY, j'obtiens de très grandes valeurs.
console.log (pos): // x: -1474.1436403989792, y: -730.829023361206, z: 3.0004000663757324
et après l'avoir multipliée par jqdiv, la fonction renvoie de très gros x et y.
Qu'est-ce que je fais mal?
-
Répondez directement à cet e-mail ou affichez-le sur GitHub.

@arieljake

Comme indiqué dans les instructions , les demandes d'aide doivent être dirigées vers stackoverflow . Ce tableau est pour les bogues et les demandes de fonctionnalités.

bien ... mais mr doob lui-même a mis du code, alors qu'est-ce que ça donne?

@arieljake # 1979

Incase quiconque en a encore besoin après la mise à niveau ...

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, très vieux problème, mais j'avais un objet imbriqué, qui ne fonctionnait pas avec le code ci-dessus.
Mon cas était le suivant: je voulais la position réelle x et y (et z) pour un objet imbriqué après le rendu, j'ai donc adapté les exemples ci-dessus.
Notez s'il vous plaît:

  1. Vous donnez maintenant l'objet entier comme argument au lieu de seulement object.position dans les exemples ci-dessus.
  2. De plus, cela ne fonctionnera qu'une fois que le moteur de rendu aura terminé son travail et appelé
  3. Cela fonctionne également pour les objets non imbriqués, mais il fera quelques calculs de trop.
  4. Il vous donne également un écran-Z, qui peut être utilisé pour trier les étiquettes domElements ou zSort.
    Le relatif screen-z est compris entre 0 et 1, par rapport aux plans de découpe avant et arrière de la caméra / rendu et cela fonctionne très bien pour mes besoins (tri).
  5. Vous pouvez obtenir la largeur et la hauteur actuelles des moteurs de rendu par renderer.domElement.width et renderer.domElement.height.
scene.updateMatrixWorld(); 

et

parent.updateMatrixWorld(); 

`` `js
fonction nestedObjecttoScreenXYZ (obj, caméra, largeur, hauteur)
{
var vector = new THREE.Vector3 ();
vector.setFromMatrixPosition (obj.matrixWorld);
var widthHalf = (largeur / 2);
var heightHalf = (hauteur / 2);
vector.project (caméra);
vector.x = (vector.x * widthHalf) + widthHalf;
vector.y = - (vector.y * heightHalf) + heightHalf;
vecteur de retour;
};



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

Juste au cas où quelqu'un aurait le même problème.

Cette page vous a été utile?
0 / 5 - 0 notes