2012-07-20 6 views
27

Il existe plusieurs excellentes questions de pile (1, 2) sur unprojecting dans Three.js, c'est comment convertir (x, y) les coordonnées de la souris dans le navigateur pour le (x, y, z) coordonnées dans l'espace de toile Three.js. La plupart du temps, ils suivent ce modèle:Convertir les coordonnées du monde en coordonnées écran dans Three.js en utilisant la projection

var elem = renderer.domElement, 
     boundingRect = elem.getBoundingClientRect(), 
     x = (event.clientX - boundingRect.left) * (elem.width/boundingRect.width), 
     y = (event.clientY - boundingRect.top) * (elem.height/boundingRect.height); 

    var vector = new THREE.Vector3( 
     (x/WIDTH) * 2 - 1, 
     - (y/HEIGHT) * 2 + 1, 
     0.5 
    ); 

    projector.unprojectVector(vector, camera); 
    var ray = new THREE.Ray(camera.position, vector.subSelf(camera.position).normalize()); 
    var intersects = ray.intersectObjects(scene.children); 

je tente de faire l'inverse - au lieu d'aller de « écran monde » espace, d'aller de l'espace « monde à l'écran ». Si je connais la position de l'objet dans Three.js, comment puis-je déterminer sa position sur l'écran?

Il ne semble pas y avoir de solution publiée à ce problème. Another question about this just showed up on Stack, mais l'auteur prétend avoir résolu le problème avec une fonction qui ne fonctionne pas pour moi. Leur solution n'utilise pas de Ray projeté, et je suis à peu près sûr que 2D à 3D utilise unprojectVector(), que la solution 3D vers 2D nécessitera projectVector(). Il y a aussi this issue ouvert sur Github.

Toute aide est appréciée.

+0

Merci beaucoup pour le modèle de traduction "écran vers monde". Ce fut une douleur pendant de nombreuses heures .. – LePhleg

Répondre

31

Essayez avec ceci:

var width = 640, height = 480; 
var widthHalf = width/2, heightHalf = height/2; 

var vector = new THREE.Vector3(); 
var projector = new THREE.Projector(); 
projector.projectVector(vector.setFromMatrixPosition(object.matrixWorld), camera); 

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

un op sur une autre Stack questions posté ce lien qui a également la solution. Merci encore! https://github.com/mrdoob/three.js/issues/78 – BishopZ

+2

getPosition() a été abandonné. Utilisez ceci à la place: var vector = projector.projectVector (nouveau THREE.Vector3(). GetPositionFromMatrix (object.matrixWorld), caméra); – imbrizi

+0

Réponse mise à jour. Merci @imbrizi! – mrdoob

1

Vous ne pouvez pas convertir les coordonnées (x, y) en coordonnées (x, y, z) car vous perdez des informations. Ce que vous avez cité est comment trouver tous les points sur tous les objets de la scène qui croisent le rayon généré par (x, y).

Le passage de "monde à écran" à la demande dépend de la projection et équivaut à un seul point (x, y, z). Ce que vous faites est d'appliquer la matrice de projection à votre point (x, y, z). C'est probablement la Projector.projectVector(vector, camera) fonction à http://mrdoob.github.com/three.js/docs/49/#Projector, mais en raison du fait qu'il sort un vecteur 3d, je ne peux que supposer que l'une des dimensions est 0 et vous pouvez l'ignorer.

3

Pour Three.js moderne (R75), un vecteur peut être projeté sur l'écran avec:

var width = window.innerWidth, height = window.innerHeight; 
var widthHalf = width/2, heightHalf = height/2; 

var pos = object.position.clone(); 
pos.project(camera); 
pos.x = (pos.x * widthHalf) + widthHalf; 
pos.y = - (pos.y * heightHalf) + heightHalf; 
2

Pour tout le monde se deprecated ou warnings journaux, les La réponse acceptée est pour les anciennes versions Three.js. Maintenant, c'est encore plus facile avec:

let pos = new THREE.Vector3(); 
pos = pos.setFromMatrixPosition(object.matrixWorld); 
pos.project(camera); 

let widthHalf = canvasWidth/2; 
let heightHalf = canvasHeight/2; 

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

console.log(pos); 
+0

"objet" n'est pas défini –

Questions connexes