Three.js: unproject - Wie erhalte ich die tatsächliche Position eines bestimmten 3D-Objekts auf dem Bildschirm (oben links)?

Erstellt am 4. Jan. 2011  ·  21Kommentare  ·  Quelle: mrdoob/three.js

An Beispielen wusste ich, dass es eine Möglichkeit gibt, einen Punkt auf dem Bildschirm (x, y) auf die Punkte von '3d' zu projizieren. Aber ich kann nicht herausfinden, wie ich es zurückübersetzen soll. Vielen Dank für jeden Hinweis.

Question

Hilfreichster Kommentar

Falls jemand dies nach dem Upgrade noch benötigt ...

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;

};

Alle 21 Kommentare

Vermutlich mit dem Projektor, aber MrDoob weiß offensichtlich mehr darüber :)

Ähm, vielleicht sollten wir ein object3d.screen das ein Vector2 und es bei jedem Render aktualisieren?

Wenn dieser object3D.screen-Vektor nur zum Übersetzen der object3D.position jedes object3D in 2D verwendet wird, wäre object3D.screen dann nicht von zu geringem Wert? Ich meine: Ich denke, es wäre sinnvoller, jeden Punkt x, y, z eines beliebigen Netzes an der Position x, y, z in 2D-Koordinaten übersetzen zu können.

Dies bedeutet wiederum, dass es niemals möglich wäre, jede 3D-Position jedes Objekts vorab zu berechnen.

Es wäre imho nützlich, zum Beispiel eine Funktion THREE.3dto2d() , die entweder einen Vektor3 (der einen Punkt in der Szene darstellt) oder einen Vektor3 und ein Objekt (wobei der Vektor3 einen Punkt auf dem Objekt darstellt) verwendet.
Die Funktion berechnet dann die 3D-Position in der Szene.
Zuletzt nimmt es die Kamera, ihre Position, Drehung, die Projektionsmatrix usw. und übersetzt den Punkt zurück in 2D.

Ich denke, die Kamera sollte auch ein Parameter der Funktion sein ...

Nun ... Projector.projectScene macht das schon irgendwie;)

Ich wusste ,

Gibt es ein Beispiel dafür?

Hmm ... noch nicht ... diese Funktionen sind für die Verwendung mit dem Renderer vorgesehen ... sie geben eine Liste der zu rendernden Elemente ohne Beziehung zu den Originalobjekten zurück. Vielleicht sollte ich einfach einen Link zu den Originalobjekten setzen und das reicht ... Hmmm, ich muss das ein bisschen mehr überlegen.

Ich bin gerade in den Ferien, aber ich werde eine Lens Flare-Demo (oder so) machen, sobald ich zurück bin (nächste Woche).

Klar, genieße deine Ferien und ich freue mich auf die neue Demo! :-)

Hmm, das hat früher bei mir funktioniert (r32), in r35 nicht mehr ..

  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 nach projScreenMat.multiplyVector3(pos); früher zwischen -1 und 1 ((0,0) in der Mitte der Ansicht begrenzt), scheint jetzt aber unerwartet zu variieren.

Ja, camera.matrix muss jetzt durch camera.matrixWorldInverse .
Versuchen Sie es damit:

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

}

Ja, das hat funktioniert, wusste nichts über die Matrizenänderungen. Hoffe, diese Projektionsfunktion hat die Frage von alivedise beantwortet.

Ich denke, es ist der richtige Thread, um meine Frage zu 3D Cube zu stellen. Ich habe einen Würfel auf Leinwand mit anklickbaren Gesichtern gezeichnet. Der Würfel dreht sich frei auf der X- und Y-Achse. Was ich möchte, ist, die größte Vorderseite zu erhalten, wenn der Benutzer die Maus loslässt und sie durch automatisches Drehen vollständig sichtbar macht. Jede Hilfe in diesem Zusammenhang wäre sehr dankbar.

Vielen Dank.

@ imrantariq2011 : Das hat nicht wirklich mit diesem Problem zu tun.

Für Textur-Mapping-Zwecke möchte ich in der Lage sein, die x, y-Bildschirmkoordinaten für jeden Scheitelpunkt für ein bestimmtes Gesicht zu erhalten.

Ich kann sehen, wie dies mit der obigen Funktion (toScreenXY: Funktion) erreicht werden kann - aber zuerst sind die welttransformierten (skalierten, übersetzten und gedrehten) Eckpunkte für ein bestimmtes Gesicht erforderlich. Ich habe einige Zeit mit Projector.projectScene verbracht und mich gefragt, ob es einen einfacheren Weg gibt, um das oben genannte Ziel zu erreichen, und es sieht so aus, als würde object.matrixWorld.getPosition () den Schwerpunkt des Objekts und nicht die Gesichtsscheitelpunkte ermitteln.

Ja, der obige Code war für einen von. Wenn Sie am besten viele Punkte projizieren müssen, um die Codebits von .projectScene() selbst zu extrahieren.

Leute, die hierher kommen, möchten vielleicht etwas darüber wissen:

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

Ich benutze das, es funktioniert:

Funktion toScreenXY (pos3D)
{
var projector = new THREE.Projector ();
var v = projector.projectVector (pos3D, Kamera);
var percX = (vx + 1) / 2;
var percY = (-vy + 1) / 2;
var left = percX * window.innerWidth;
var top = percY * window.innerHeight;

return new THREE.Vector2 (links, oben);
}}

Am Freitag, den 1. August 2014 um 11:24 Uhr schrieb Artem Fitiskin [email protected] :

Wenn ich toScreenXY benutze, bekomme ich sehr große Werte.
console.log (pos): // x: -1474.1436403989792, y: -730.829023361206, z: 3.0004000663757324
und nachdem es mit jqdiv multipliziert wurde, gibt die Funktion sehr große x und y zurück.
Was mache ich falsch?
- -
Antworte direkt auf diese E-Mail oder sieh sie dir auf GitHub an.

@arieljake

Wie in den Richtlinien angegeben , sollten Hilfeanfragen an den

gut ... aber Herr Doob selbst hat Code eingegeben, also was gibt es?

@arieljake # 1979

Falls jemand dies nach dem Upgrade noch benötigt ...

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, sehr altes Problem, aber ich hatte ein verschachteltes Objekt, das mit dem obigen Code nicht funktionierte.
Mein Fall war: Ich wollte die reale x-und-y (und z) Position für ein verschachteltes Objekt nach dem Rendern, also habe ich die obigen Beispiele angepasst.
Bitte beachten Sie:

  1. Sie geben jetzt das gesamte Objekt als Argument an, anstatt nur die object.position in den obigen Beispielen.
  2. Dies funktioniert auch erst, nachdem der Renderer seine Arbeit erledigt und aufgerufen hat
  3. Es funktioniert auch für nicht verschachtelte Objekte, führt jedoch einige Berechnungen zu viele durch.
  4. Außerdem erhalten Sie ein Bildschirm-Z, mit dem Sie domElements oder zSort-Labels sortieren können.
    Der Bildschirm-z-Relativ liegt zwischen 0 und 1, relativ zu den vorderen und hinteren Schnittebenen der Kamera / des Renderers, und dies funktioniert für meine Zwecke einwandfrei (Sortieren).
  5. Sie können die aktuelle Breite und Höhe des Renderers über renderer.domElement.width und renderer.domElement.height abrufen.
scene.updateMatrixWorld(); 

und

parent.updateMatrixWorld(); 

`` `js
Funktion nestedObjecttoScreenXYZ (Objekt, Kamera, Breite, Höhe)
{
var vector = new THREE.Vector3 ();
vector.setFromMatrixPosition (obj.matrixWorld);
var widthHalf = (width / 2);
var heightHalf = (height / 2);
vector.project (Kamera);
vector.x = (vector.x * widthHalf) + widthHalf;
vector.y = - (vector.y * heightHalf) + heightHalf;
Rückgabevektor;
};



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

Nur für den Fall, dass jemand auf das gleiche Problem stößt.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

jlaquinte picture jlaquinte  ·  3Kommentare

yqrashawn picture yqrashawn  ·  3Kommentare

Horray picture Horray  ·  3Kommentare

fuzihaofzh picture fuzihaofzh  ·  3Kommentare

seep picture seep  ·  3Kommentare