a

Câu hỏi Cách lấy đối tượng trong không gian 3D WebGL từ một phối hợp nhấp chuột


Tôi đang xây dựng một bảng trò chơi trong WebGL. Bảng có thể được xoay / thu nhỏ. Tôi cần một cách để dịch một nhấp chuột trên phần tử canvas (x, y) vào điểm liên quan trong không gian 3D (x, y, z). Kết quả cuối cùng là tôi muốn biết tọa độ (x, y, z) có chứa điểm chạm đối tượng gần nhất với người dùng. Ví dụ, người dùng nhấp vào một mảnh, và bạn tưởng tượng một tia đi qua không gian 3D đi qua cả phần và bảng trò chơi, nhưng tôi muốn điều phối (x, y, z) của phần tại điểm mà nó xúc động.

Tôi cảm thấy như thế này phải là một vấn đề rất phổ biến, nhưng tôi dường như không thể tìm thấy một giải pháp trong googles của tôi. Phải có một số cách để hiển thị chế độ xem hiện tại của không gian 3D thành 2D để bạn có thể ánh xạ từng điểm trong không gian 2D tới điểm liên quan trong không gian 3D. Tôi muốn người dùng có thể di chuột qua một không gian trên bảng và có màu thay đổi điểm.


14
2017-09-09 16:26


gốc


Bạn không nói về điều này là bạn? 3dkingdoms.com/selection.html#ray Chỉ cần thả bình thường từ ống kính camera xuống mặt phẳng và tìm ra POI. - Incognito
Tôi nghĩ điều này là mô tả chung về những gì tôi muốn làm nhưng tôi không thể tìm ra thuật toán từ mô tả của anh ấy. - seibelj
Phải có một số loại tính toán từ việc tưởng tượng khung nhìn như mặt phẳng phẳng, nằm ở (0,0,0) và tâm của hình chữ nhật ở gốc. Tôi sẽ suy nghĩ về điều này nhiều hơn, tôi tự tin có một giải pháp thanh lịch. - seibelj


Các câu trả lời:


Bạn đang tìm kiếm một chức năng không dự đoán, chuyển đổi tọa độ màn hình thành một dàn diễn viên từ vị trí máy ảnh vào thế giới 3D. Sau đó, bạn phải thực hiện các thử nghiệm giao cắt tia / tam giác để tìm hình tam giác gần nhất với máy ảnh mà cũng cắt giao tia.

Tôi có một ví dụ về dự án không có sẵn tại jax / camera.js # L568 - nhưng bạn vẫn sẽ cần phải thực hiện giao điểm ray / tam giác. Tôi đã thực hiện điều đó tại jax / tam.js # L113.

Có một lựa chọn đơn giản hơn và (thường) nhanh hơn, tuy nhiên, được gọi là 'chọn'. Sử dụng điều này nếu bạn muốn chọn toàn bộ một đối tượng (ví dụ, một quân cờ), và nếu bạn không quan tâm đến nơi con chuột thực sự được bấm. Cách WebGL để thực hiện điều này là hiển thị toàn bộ cảnh trong các sắc thái khác nhau của màu xanh (màu xanh dương là một khóa, trong khi màu đỏ và màu xanh lá cây được sử dụng cho các ID duy nhất của các đối tượng trong cảnh) thành một kết cấu, sau đó đọc lại một pixel kết cấu đó. Giải mã RGB vào ID của đối tượng sẽ cung cấp cho bạn đối tượng đã được nhấp. Một lần nữa, tôi đã thực hiện điều này và nó có sẵn tại jax / world.js # L82. (Xem thêm dòng 146, 162, 175.)

Cả hai cách tiếp cận đều có ưu và nhược điểm (được thảo luận đây và trong một số ý kiến ​​sau) và bạn sẽ cần phải tìm ra phương pháp nào tốt nhất phục vụ nhu cầu của bạn. Chọn chậm hơn với những cảnh rất lớn, nhưng không được dự đoán trong JS thuần túy là cực kỳ chậm (vì JS chính nó không phải là tất cả nhanh) nên đề xuất tốt nhất của tôi là thử nghiệm cả hai.

FYI, bạn cũng có thể xem xét dự án GLU và mã dự án, mà tôi dựa vào mã của tôi một cách lỏng lẻo khi: http://www.opengl.org/wiki/GluProject_and_gluUnProject_code


19
2017-09-10 18:27



Để làm rõ: chọn trong WebGL thường nhanh hơn unprojecting hoàn toàn vì JS là chậm, và chọn lấy lợi thế của GPU để tăng tốc phần cứng, do đó bỏ qua nút cổ chai JS. Trong một triển khai C truyền thống, không thể dự đoán có lẽ là cách để đi, đặc biệt nếu bạn chỉ cần kiểm tra một số lượng rất nhỏ các hình tam giác. - sinisterchipmunk
Wow, cảm ơn rất nhiều, tôi sẽ xem xét tất cả những điều này. Điều này hoàn toàn trả lời câu hỏi của tôi. - seibelj
Vì vậy, nếu tôi cần biết chính xác tam giác / đỉnh, chọn là không đủ? - Drew
Chính xác. Bạn có thể hack theo cách của bạn bằng cách vẽ từng hình tam giác với màu chọn khác nhau, nhưng điều này sẽ rất chậm (tôi nghi ngờ nó có thể tồn tại trong JavaScript, nhưng những điều lạ đã xảy ra) vì nó sẽ yêu cầu một đường chuyền mới cho mỗi tam giác. Đối với thông tin tam giác / đỉnh chính xác, đặt cược tốt nhất của bạn là không được chiếu. - sinisterchipmunk
Chỉ cần làm rõ, thuật ngữ "chọn" không liên quan đến bất kỳ kỹ thuật cụ thể nào được sử dụng. Cũng tùy thuộc vào cấu trúc của việc chọn mã thông qua màu sắc có thể trở nên rất chậm khi có vài nghìn đối tượng hiển thị trên màn hình. Đó là lý do tại sao tôi sẽ khuyên bạn nên chọn tia với một phân khu không gian thích hợp được áp dụng (cho cả cảnh và hình tam giác lưới). - LJᛃ


Đây là bản demo làm việc

function onMouseUp(event) {

    event.preventDefault();        
    x_pos = (event.clientX / window.innerWidth) * 2 - 1;
    y_pos = -(event.clientY / window.innerHeight) * 2 + 1;
    z_pos = 0.5;

    var vector = new THREE.Vector3( x_pos , y_pos , z_pos );

    var projector = new THREE.Projector();
    projector.unprojectVector(vector, camera);
    var raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
    var intersects = raycaster.intersectObjects(intersectObjects);

    if (intersects.length > 0) {

        xp = intersects[0].point.x.toFixed(2);
        yp = intersects[0].point.y.toFixed(2);
        zp = intersects[0].point.z.toFixed(2);  
        destination = new THREE.Vector3( xp , yp , zp );

        radians =  Math.atan2( ( driller.position.x - xp) , (driller.position.z - zp));
        radians += 90 * (Math.PI / 180);
        console.log(radians);

        var tween = new TWEEN.Tween(driller.rotation).to({ y : radians },200).easing(TWEEN.Easing.Linear.None).start();

    }

weissner-doors.de/drone/


2
2018-06-28 08:44





Tôi đang làm việc về vấn đề này vào lúc này - cách tiếp cận tôi đang thực hiện là

  1. Hiển thị các đối tượng để chọn bộ đệm với màu duy nhất
  2. Đọc pixel đệm, ánh xạ trở lại đối tượng đã chọn
  3. Render đối tượng đã chọn vào vùng đệm với mỗi pixel pixel một hàm của Z-depth
  4. Đọc pixel đệm, ánh xạ trở lại độ sâu Z
  5. Chúng tôi đã chọn đối tượng và xấp xỉ Z cho coords chọn

1
2017-10-16 13:44





được cấy từ một trong các chủ đề. không chắc chắn về (x, y, z) nhưng bạn có thể nhận được canvas(x,y) sử dụng

getBoundingClientRect ()

function getCanvasCoord(){
  var mx = event.clientX;
  var my = event.clientY;
  var canvas = document.getElementById('canvasId');
  var rect = canvas.getBoundingClientRect();// check if your browser supports this
  mx = mx - rect.left;
  my = my - rect.top;
  return {x: mx , y: my};
}

0
2017-07-02 04:59