2011-10-31 39 views
18

Tôi có cảnh THREE.js nơi có rất nhiều phần tử xuất hiện và tôi cần phát hiện đối tượng nào người dùng đang nhấp vào.Phát hiện đối tượng được nhấp trong THREE.js

Điều tôi đã làm cho đến thời điểm này là như sau. Máy ảnh không di chuyển nhiều - nó chỉ thay đổi vị trí dọc theo một lượng giới hạn, luôn hướng về cùng một điểm. Phương pháp gần đúng của tôi là như sau:

  • Tôi lấy tọa độ nếu bấm tương đối so với vải
  • tôi dịch chúng thành toạ độ ngang và dọc trong cảnh WebGL bằng phương tiện của một rescaling đơn giản, và thêm một Z phối hợp đủ xa.
  • Tôi lấy một tia ngang bắt đầu từ điểm trên, được xây dựng bởi THREE.Ray()
  • Tôi sử dụng ray.intersectObjects() để tìm phần tử đầu tiên dọc theo tia.

Phương pháp này xấp xỉ, nhưng đôi khi chỉ cách điểm thực tế vài điểm ảnh.

Có kỹ thuật đáng tin cậy hơn để tìm ra đối tượng mà người dùng đã nhấp vào không?

+0

Lề và đệm có thể khiến cho tọa độ của bạn bị lệch bit. Bạn có tài khoản cho nó? – Prusse

+0

Hiện tại trong bản demo không có lề và phần đệm, nhưng kỹ thuật mà tôi mô tả vẫn chưa chính xác. – Andrea

+4

Hãy xem [ví dụ này] (http://mrdoob.github.com/three.js/examples/canvas_interactive_cubes.html). –

Trả lời

7

Phụ thuộc vào loại máy ảnh bạn đang sử dụng.

1) PerspectiveCamera: là link ok mà Mr.doob cung cấp.
2) OrthographicCamera: là khá khác nhau:

var init = function() { 
    camera = new THREE.OrthographicCamera(SCREEN_WIDTH/- 2, SCREEN_WIDTH/2, SCREEN_HEIGHT/2, SCREEN_HEIGHT/- 2, NEAR, FAR); 
    document.addEventListener('mousedown', onDocumentMouseDown, false); 
} 

function onDocumentMouseDown(e) { 
    e.preventDefault(); 
    var mouseVector = new THREE.Vector3(); 
    mouseVector.x = 2 * (e.clientX/SCREEN_WIDTH) - 1; 
    mouseVector.y = 1 - 2 * (e.clientY/SCREEN_HEIGHT); 
    var raycaster = projector.pickingRay(mouseVector.clone(), camera); 
    var intersects = raycaster.intersectObject(TARGET); 
    for(var i = 0; i < intersects.length; i++) { 
    var intersection = intersects[ i ], 
    obj = intersection.object; 
    console.log("Intersected object", obj); 
    } 
} 
+0

"projector.pickingRay" bị xóa? –

+2

đây là giải pháp thay thế https://github.com/mrdoob/three.js/issues/5587 –

3

Check-out này:

var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 1, 5000); 
var object; //your object 

document.addEventListener('mousedown', onMouseDown, false); 

function onMouseDown(e) { 
    var vectorMouse = new THREE.Vector3(//vector from camera to mouse 
     -(window.innerWidth/2-e.clientX)*2/window.innerWidth, 
     (window.innerHeight/2-e.clientY)*2/window.innerHeight, 
     -1/Math.tan(22.5*Math.PI/180)); //22.5 is half of camera frustum angle 45 degree 
    vectorMouse.applyQuaternion(camera.quaternion); 
    vectorMouse.normalize();   

    var vectorObject = new THREE.Vector3(); //vector from camera to object 
    vectorObject.set(object.x - camera.position.x, 
        object.y - camera.position.y, 
        object.z - camera.position.z); 
    vectorObject.normalize(); 
    if (vectorMouse.angleTo(vectorObject)*180/Math.PI < 1) { 
     //mouse's position is near object's position 

    } 
} 
+0

đây là giải pháp rất tốt và ngăn chặn một chương trình truyền hình chuyên sâu cpu, nhưng chỉ thấy nếu chuột nhấp gần trục của đối tượng . Avantage là một đối tượng không có mesh aso sẽ hoạt động theo cách này. Nhược điểm là "điểm nóng" tròn. – Hacky

2

Kiểm tra cho giao điểm của chuột và bất kỳ khối trong không gian 3d và làm thay đổi màu sắc của nó. Có thể this giúp bạn.

+3

Chào mừng bạn đến với Stack Overflow! Hãy dành một phút để đọc qua [Cách trả lời] (http://stackoverflow.com/questions/how-to-answer) - điều này có vẻ hữu ích nhưng nó sẽ được hưởng lợi từ một số giải thích về mã, xem xét [sửa] http://stackoverflow.com/posts/41385887/edit)-ing that in? –

0

Tôi đã gặp phải sự cố khi triển khai cài đặt này cho canvas không chiếm toàn bộ chiều rộng và chiều cao của màn hình. Đây là giải pháp tôi tìm thấy hoạt động khá tốt.

Khởi tạo tất cả mọi thứ trên một canvas hiện:

var init = function() { 
    var canvas_model = document.getElementById('model') 
    var viewSize = 50 // Depending on object size, canvas size etc. 
    var camera = new THREE.OrthographicCamera(-canvas_model.clientWidth/viewSize, canvas_model.clientWidth/viewSize, canvas_model.clientHeight/viewSize, -canvas_model.clientHeight/viewSize, 0.01, 2000), 
} 

Thêm một event listener vào khung:

canvas_model.addEventListener('click', function(event){ 
    var bounds = canvas_model.getBoundingClientRect() 
    mouse.x = ((event.clientX - bounds.left)/canvas_model.clientWidth) * 2 - 1; 
    mouse.y = - ((event.clientY - bounds.top)/canvas_model.clientHeight) * 2 + 1; 
    raycaster.setFromCamera(mouse, camera); 
    var intersects = raycaster.intersectObjects(scene.children, true); 
    if (intersects.length > 0) { 
    // Do stuff 
    } 
}, false) 

Hoặc cho một sự kiện 'touchstart', thay đổi dòng tính mouse.x và mouse.y vào:

mouse.x = ((event.touches[0].clientX - bounds.left)/canvas_model.clientWidth) * 2 - 1; 
mouse.y = - ((event.touches[0].clientY - bounds.top)/canvas_model.clientHeight) * 2 + 1; 
Các vấn đề liên quan