Three.js: unproject - كيف تحصل على الموضع الحقيقي على "الشاشة (أعلى ، يسار)" لكائن ثلاثي الأبعاد محدد؟

تم إنشاؤها على ٤ يناير ٢٠١١  ·  21تعليقات  ·  مصدر: mrdoob/three.js

على سبيل المثال ، علمت أن هناك طريقة ما لإسقاط نقطة واحدة على الشاشة (س ، ص) على نقاط '3d'. لكن لا يمكنني معرفة كيفية ترجمتها مرة أخرى. شكرا على اي دليل

Question

التعليق الأكثر فائدة

إذا كان أي شخص لا يزال بحاجة إلى هذا بعد الترقية ...

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;

};

ال 21 كومينتر

ربما باستخدام جهاز العرض ، ولكن من الواضح أن MrDoob يعرف المزيد عن هذا :)

حسنًا ، ربما يجب أن يكون لدينا object3d.screen والذي سيكون Vector2 وتحديثه في كل تصيير؟

إذا تم استخدام متجه object3D.screen فقط لترجمة object3D.position لكل object3D إلى 2D ، فهل لن تكون قيمة object3D.screen قليلة جدًا؟ أعني: أعتقد أنه سيكون من الأفضل أن تكون قادرًا على ترجمة أي نقطة س ، ص ، ض من أي شبكة في الموضع س ، ص ، ض إلى إحداثيات ثنائية الأبعاد.

وهذا بدوره يعني أنه لن يكون من الممكن أبدًا إجراء حساب مسبق لكل موضع ثلاثي الأبعاد لكل كائن.

قد يكون من المفيد أن يكون لديك على سبيل المثال دالة THREE.3dto2d() تأخذ إما Vector3 (تمثل نقطة في المشهد) أو Vector3 وكائن (حيث يمثل Vector3 نقطة على الكائن).
تقوم الوظيفة بعد ذلك بحساب موضع ثلاثي الأبعاد في المشهد.
أخيرًا ، يأخذ الكاميرا وموقعها ودورانها ومصفوفة الإسقاط وما إلى ذلك ، وترجم النقطة مرة أخرى إلى 2D.

أعتقد أن الكاميرا يجب أن تكون معلمة للوظيفة أيضًا ...

حسنًا ... Projector.projectScene بذلك بالفعل ؛)

انظر ، كنت أعلم أنه كان جهاز العرض ... ؛-)

هل هناك مثال يستخدمه؟

حسنًا ... ليس بعد ... تم تصميم هذه الوظائف لتستخدم مع العارض ... فهي تعيد قائمة بالعناصر المراد عرضها بدون علاقة بالكائنات الأصلية. ربما يجب أن أضع رابطًا للأشياء الأصلية وهذا سيفعل ... هممم ، أحتاج إلى التفكير في ذلك أكثر قليلاً.

أنا حاليًا في إجازات ، لكنني سأقدم عرضًا توضيحيًا لتوهج العدسة (أو شيء ما) بمجرد عودتي (الأسبوع المقبل).

بالتأكيد ، استمتع بعطلتك وأنا أتطلع إلى الإصدار التجريبي الجديد! :-)

حسنًا ، كان هذا يعمل معي (r32) ، ولم يعد في 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 }; 
  },

تم استخدام نقاط البيع بعد projScreenMat.multiplyVector3(pos); بين -1 و 1 ((0،0) في مركز الرؤية.) ، ولكن يبدو الآن أنه يختلف بشكل غير متوقع ..

نعم ، يجب استبدال camera.matrix الآن بـ camera.matrixWorldInverse .
جرب مع هذا:

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

}

نعم ، لقد نجحت ، لم أكن أعرف عن تغييرات المصفوفات. آمل أن تكون وظيفة الإسقاط هذه قد أجابت على سؤال الحي.

أعتقد أنه الخيط الصحيح لطرح سؤالي بخصوص 3D Cube. لدي مكعب مرسوم على قماش ذو وجوه قابلة للنقر. يدور المكعب بحرية على المحور X والمحور Y. ما أريده هو الحصول على أقصى وجه أمامي عند تحرير المستخدم للماوس وجعله مرئيًا بالكامل عن طريق الدوران تلقائيًا. أي مساعدة في هذا السياق ستكون في غاية الامتنان.

شكرا لك.

@ imrantariq2011 : هذا ليس مرتبطًا حقًا بهذه المشكلة ، هل تمانع في فتح واحدة جديدة؟ شكر.

لأغراض رسم الخرائط ، أود أن أتمكن من الحصول على إحداثيات الشاشة x و y لكل قمة لوجه معين.

أستطيع أن أرى كيف يمكن القيام بذلك باستخدام ما ورد أعلاه (toScreenXY: function) - ولكن أولاً يلزم العالم المحول (المقياس والترجمة والدوران) لوجه معين. لقد أمضيت بعض الوقت في النظر إلى Projector.projectScene وأتساءل عما إذا كانت هناك طريقة أبسط لتحقيق الهدف أعلاه ويبدو أن object.matrixWorld.getPosition () قد تحصل على النقطه الوسطى للكائن بدلاً من رؤوس الوجه.

نعم ، كان الرمز أعلاه لأحد ملفات. إذا كنت بحاجة إلى عرض العديد من النقاط ، إذا كان من الأفضل لك استخراج أجزاء الكود من .projectScene() نفسها.

قد يرغب الأشخاص الذين يصلون إلى هنا في معرفة هذا:

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

أنا أستخدم هذا ، إنه يعمل:

الوظيفة toScreenXY (pos3D)
{
var projector = new THREE.Projector () ؛
var v = projector.projectVector (pos3D ، camera) ؛
var percX = (vx + 1) / 2 ؛
فار percY = (-vy + 1) / 2 ؛
var يسار = percX * window.innerWidth ؛
var top = percY * window.innerHeight ؛

إرجاع ثلاثة جديدة. Vector2 (يسار ، أعلى) ؛
}

يوم الجمعة ، 1 أغسطس 2014 الساعة 11:24 صباحًا ، كتب Artem Fitiskin [email protected] :

عندما أستخدم toScreenXY ، أحصل على قيم كبيرة جدًا.
console.log (نقاط البيع): // x: -1474.1436403989792، y: -730.829023361206، z: 3.0004000663757324
وبعد ضربها بـ jqdiv ، تُرجع الدالة x و y الكبيرتين جدًا.
ما الذي أفعله خطأ؟
-
قم بالرد على هذا البريد الإلكتروني مباشرة أو قم بعرضه على GitHub.

تضمين التغريدة

كما هو مذكور في الإرشادات ، يجب توجيه طلبات المساعدة إلى تدفق التكديس . هذا المنتدى مخصص للأخطاء وطلبات الميزات.

بخير ... لكن السيد doob نفسه وضع التعليمات البرمجية ، فماذا يعطي؟

arieljake # 1979

إذا كان أي شخص لا يزال بحاجة إلى هذا بعد الترقية ...

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;

};

حسنًا ، مشكلة قديمة جدًا ، لكن كان لدي كائن متداخل لا يعمل مع الكود أعلاه.
كانت حالتي هي: أردت الموضع الحقيقي x-and-y (و z) لكائن متداخل بعد التصيير ، لذلك قمت بتكييف الأمثلة أعلاه.
يرجى الملاحظة:

  1. أنت الآن تعطي الكائن بأكمله كوسيطة بدلاً من وضع الكائن فقط في الأمثلة أعلاه.
  2. أيضًا لن يعمل هذا إلا بعد أن يقوم العارض بعمله واستدعائه
  3. تعمل أيضًا مع الكائنات غير المتداخلة ، ولكنها ستؤدي بعض العمليات الحسابية كثيرًا جدًا.
  4. يمنحك أيضًا شاشة Z ، والتي يمكن استخدامها لفرز domElements أو zSort تسميات.
    يتراوح نسبي الشاشة z بين 0 و 1 ، بالنسبة إلى مستويات القطع الأمامية والخلفية للكاميرا / العارض وهذا يعمل بشكل جيد لأغراضي (الفرز).
  5. يمكنك الحصول على العرض والارتفاع الحاليين للعارضين من خلال Renderer.domElement.width و Renderer.domElement.height.
scene.updateMatrixWorld(); 

و

parent.updateMatrixWorld(); 

شبيبة
دالة متداخلةObjecttoScreenXYZ (كائن ، كاميرا ، عرض ، ارتفاع)
{
متجه var = جديد THREE.Vector3 () ؛
vector.setFromMatrixPosition (obj.matrixWorld) ؛
var widthHalf = (العرض / 2) ؛
var heightHalf = (الارتفاع / 2) ؛
vector.project (الكاميرا) ؛
vector.x = (vector.x * widthHalf) + widthHalf ؛
vector.y = - (vector.y * heightHalf) + heightHalf ؛
ناقلات العودة
} ؛



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

فقط في حالة تعرض أي شخص لنفس المشكلة.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات

القضايا ذات الصلة

clawconduce picture clawconduce  ·  3تعليقات

boyravikumar picture boyravikumar  ·  3تعليقات

akshaysrin picture akshaysrin  ·  3تعليقات

Horray picture Horray  ·  3تعليقات

makc picture makc  ·  3تعليقات