Three.js: unproject - Bagaimana cara mendapatkan posisi sebenarnya di 'layar (atas, kiri)' objek 3d tertentu?

Dibuat pada 4 Jan 2011  ·  21Komentar  ·  Sumber: mrdoob/three.js

Sebagai contoh, saya tahu ada cara untuk memproyeksikan satu titik di layar (x, y) ke titik '3d'. Tapi saya tidak tahu bagaimana menerjemahkannya kembali. Terima kasih atas petunjuknya.

Question

Komentar yang paling membantu

Jika ada orang yang masih membutuhkan ini setelah meningkatkan ...

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;

};

Semua 21 komentar

Mungkin menggunakan Proyektor, tetapi MrDoob jelas tahu lebih banyak tentang ini :)

Uhm, mungkin kita harus memiliki object3d.screen yang akan menjadi Vector2 dan memperbaruinya di setiap render?

Jika Vector object3D.screen itu hanya digunakan untuk menerjemahkan object3D.position dari setiap object3D ke 2D, maka apakah object3D.screen tidak akan memiliki nilai yang terlalu kecil? Maksud saya: Saya pikir akan lebih berguna untuk dapat menerjemahkan titik x, y, z dari sembarang mesh pada posisi x, y, z ke koordinat 2D.

Itu pada gilirannya berarti tidak mungkin untuk menghitung sebelumnya setiap posisi 3D dari setiap objek.

Akan sangat berguna untuk memiliki, misalnya fungsi THREE.3dto2d() yang mengambil Vector3 (mewakili titik dalam adegan) atau Vector3 dan objek (di mana Vector3 mewakili titik pada objek).
Fungsi tersebut kemudian menghitung posisi 3D di tempat kejadian.
Akhirnya, ia mengambil kamera, posisinya, rotasinya, projectionMatrix, dll, dan menerjemahkan titik itu kembali ke 2D.

Saya kira kamera harus menjadi parameter fungsinya juga ...

Yah ... Projector.projectScene agak sudah melakukannya;)

Lihat, saya tahu itu adalah Proyektor ... ;-)

Apakah ada contoh yang menggunakannya?

Hmm ... belum ... fungsi tersebut didesain untuk digunakan dengan Renderer ... mereka mengembalikan daftar elemen untuk dirender tanpa kaitannya dengan objek aslinya. Mungkin sebaiknya aku meletakkan beberapa tautan ke objek aslinya dan itu akan ... Hmmm, perlu dipikirkan lagi.

Saat ini saya sedang liburan, tapi saya akan melakukan demo suar lensa (atau semacamnya) segera setelah saya kembali (minggu depan).

Oke, nikmati liburan Anda dan saya menantikan demo baru! :-)

Hmm, ini dulu berfungsi untuk saya (r32), tidak lagi di 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 setelah projScreenMat.multiplyVector3(pos); biasanya dibatasi antara -1 dan 1 ((0,0) di tengah tampilan.), tetapi sekarang tampaknya berubah secara tidak terduga ..

Ya, camera.matrix perlu diganti sekarang dengan camera.matrixWorldInverse .
Coba dengan ini:

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

}

Yup itu berhasil, tidak tahu tentang perubahan matriks. Semoga fungsi proyeksi ini menjawab pertanyaan alivedise.

Saya pikir ini adalah utas yang tepat untuk mengajukan pertanyaan saya tentang 3D Cube. Saya memiliki kubus yang digambar di atas kanvas dengan wajah yang dapat diklik. Kubus berputar bebas pada sumbu X dan sumbu Y. Yang saya inginkan adalah mendapatkan tampilan paling depan saat pengguna melepaskan mouse dan membuatnya terlihat sepenuhnya dengan memutar otomatis. Bantuan apa pun dalam konteks ini akan sangat dihargai.

Terima kasih.

@ imrantariq2011 : Itu tidak benar-benar terkait dengan masalah ini, apakah Anda keberatan membuka yang baru? Terima kasih.

Untuk tujuan pemetaan tekstur, saya ingin mendapatkan koordinat layar x, y untuk setiap simpul untuk wajah tertentu.

Saya dapat melihat bagaimana ini dapat dilakukan dengan menggunakan (toScreenXY: function) di atas - tetapi pertama-tama dunia yang ditransformasikan (diskalakan, diterjemahkan, dan diputar) simpul untuk wajah tertentu diperlukan. Saya telah menghabiskan beberapa waktu melihat Projector.projectScene dan saya bertanya-tanya apakah ada cara yang lebih sederhana untuk mencapai tujuan di atas dan sepertinya object.matrixWorld.getPosition () mungkin mendapatkan pusat massa objek daripada simpul wajah.

Ya, kode di atas adalah untuk salah satu. Jika Anda perlu memproyeksikan banyak poin jika sebaiknya mengekstrak potongan kode dari .projectScene() itu sendiri.

orang yang sampai di sini mungkin ingin tahu tentang ini:

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

Saya menggunakan ini, itu berhasil:

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

kembali baru THREE.Vector2 (kiri, atas);
}

Pada hari Jumat, 1 Agustus 2014 11:24, Artem Fitiskin [email protected] menulis:

Saat saya menggunakan toScreenXY, saya mendapatkan nilai yang sangat besar.
console.log (pos): // x: -1474.1436403989792, y: -730.829023361206, z: 3.0004000663757324
dan setelah mengalikannya dengan jqdiv, fungsi mengembalikan x dan y yang sangat besar.
Apa yang saya lakukan salah?
-
Balas email ini secara langsung atau lihat di GitHub.

@arielkrisna

Seperti yang dinyatakan dalam pedoman , permintaan bantuan harus diarahkan ke stackoverflow . Papan ini untuk bug dan permintaan fitur.

baik-baik saja ... namun mr doob sendiri memasukkan kode, jadi apa yang menyebabkannya?

@arielake # 1979

Jika ada orang yang masih membutuhkan ini setelah meningkatkan ...

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;

};

Oke, masalah yang sangat lama, tetapi saya memiliki objek bersarang, yang tidak berfungsi dengan kode di atas.
Kasus saya adalah: Saya menginginkan posisi x-and-y (dan z) yang sebenarnya untuk objek bersarang setelah rendering, jadi saya mengadaptasi contoh di atas.
Tolong dicatat:

  1. Sekarang Anda memberikan keseluruhan objek sebagai argumen, bukan hanya objek.posisi pada contoh di atas.
  2. Juga ini hanya akan bekerja setelah perender menyelesaikan tugasnya dan dipanggil
  3. Ini juga berfungsi untuk objek yang tidak bersarang, tetapi akan melakukan terlalu banyak perhitungan.
  4. Ini juga memberi Anda layar-Z, yang dapat digunakan untuk mengurutkan domElements atau label zSort.
    Relatif layar-z adalah antara 0 dan 1, relatif terhadap bidang kliping depan dan belakang kamera / penyaji dan ini berfungsi dengan baik untuk tujuan saya (penyortiran).
  5. Anda bisa mendapatkan lebar dan tinggi perender saat ini dengan renderer.domElement.width dan renderer.domElement.height.
scene.updateMatrixWorld(); 

dan

parent.updateMatrixWorld(); 

`` js
function nestedObjecttoScreenXYZ (obj, kamera, lebar, tinggi)
{
var vector = new THREE.Vector3 ();
vector.setFromMatrixPosition (obj.matrixWorld);
var widthHalf = (lebar / 2);
var heightHalf = (tinggi / 2);
vector.project (kamera);
vector.x = (vector.x * widthHalf) + widthHalf;
vector.y = - (vector.y * heightHalf) + heightHalf;
vektor kembali;
};



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

Untuk berjaga-jaga jika ada yang mengalami masalah yang sama.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat