web-dev-qa-db-fra.com

Conversion des coordonnées mondiales en coordonnées d'écran dans Three.js à l'aide de la projection

Il y a plusieurs excellentes questions sur la pile ( 1 , 2 ) à propos de la non-projection dans Three.js, c'est comment convertir les coordonnées de la souris (x, y) dans le navigateur en ( coordonnées x, y, z) dans l'espace de travail Three.js. La plupart du temps, ils suivent ce modèle:

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

J'ai essayé de faire l'inverse - au lieu d'aller de l'espace "écran au monde", d'aller de l'espace "monde à é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. ne autre question à ce sujet vient d'apparaître sur 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 Rayon projeté, et je suis à peu près sûr que, puisque la 2D vers la 3D utilise unprojectVector (), que la solution 3D vers la 2D nécessitera projectVector ().

Il y a aussi ce problème ouvert sur Github.

Toute aide est appréciée.

31
BishopZ

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;
34
mrdoob

Pour les Three.js modernes (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;
7
dkobozev

Pour tous ceux qui obtiennent des journaux deprecated ou warnings, la réponse acceptée est pour les anciennes versions de Three.js. Maintenant, c'est encore plus simple 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);
6
martin

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é, c'est comment trouver tous les points sur tous les objets de la scène qui coupent le rayon généré par (x, y).

Le passage du "monde à l'écran" comme vous le demandez est ce qu'est la projection et équivaut à rendre un seul point (x, y, z). Ce que vous faites, c'est appliquer la matrice de projection à votre point (x, y, z). Il s'agit probablement de la fonction Projector.projectVector(vector, camera) à http://mrdoob.github.com/three.js/docs/49/#Projector , mais en raison du fait qu'elle génère un Vecteur 3D, je peux seulement supposer que l'une des dimensions est 0 et vous pouvez l'ignorer.

0
ninjagecko