2011-10-31 14 views
18

में क्लिक की गई वस्तु का पता लगाएं मेरे पास एक THREE.js दृश्य है जहां बहुत से तत्व दिखाई देते हैं, और मुझे यह पता लगाने की आवश्यकता है कि उपयोगकर्ता किस ऑब्जेक्ट पर क्लिक कर रहा है।THREE.js

जो मैंने अभी तक किया है वह निम्नलिखित है। कैमरा ज्यादा नहीं बढ़ता है - यह केवल एक ही राशि की ओर देखकर, सीमित राशि से ऊर्ध्वाधर स्थिति को बदलता है।

  • मैं निर्देशांक ले कैनवास के लिए क्लिक रिश्तेदार
  • मैं उन्हें WebGL दृश्य में क्षैतिज और ऊर्ध्वाधर निर्देशांक में एक सरल rescaling के माध्यम से अनुवाद करते हैं, और एक जेड जोड़ें: मेरे अनुमानित विधि निम्नलिखित है समन्वय जो काफी दूर है।
  • मैं उपरोक्त बिंदु से शुरू होने वाली क्षैतिज किरण लेता हूं, तीन द्वारा निर्मित। रे()
  • मैं रे के साथ पहला तत्व खोजने के लिए ray.intersectObjects() का उपयोग करता हूं।

यह विधि लगभग काम करती है, लेकिन कभी-कभी वास्तविक बिंदु से कुछ पिक्सल दूर होती है।

क्या उस ऑब्जेक्ट को खोजने के लिए कोई और विश्वसनीय तकनीक है जहां उपयोगकर्ता ने क्लिक किया है?

+0

मार्जिन और पैडिंग आपके समन्वय को थोड़ा ऑफसेट होने का कारण बन सकता है। क्या आपने इसके लिए जिम्मेदार ठहराया? – Prusse

+0

डेमो में इस समय कोई मार्जिन और न ही पैडिंग हैं, लेकिन मैंने जो तकनीक वर्णित की है वह वैसे भी सटीक नहीं है। – Andrea

+4

[इस उदाहरण] पर एक नज़र डालें (http://mrdoob.github.com/three.js/examples/canvas_interactive_cubes.html)। –

उत्तर

7

इस बात पर निर्भर करता है कि आप किस प्रकार के कैमरे का उपयोग कर रहे हैं।

1) PerspectiveCamera: ठीक है लिंक है कि Mr.doob प्रदान करता है।
2) OrthographicCamera: काफी अलग है:

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" हटा दिया गया है? –

+2

यहां एक वैकल्पिक समाधान https://github.com/mrdoob/three.js/issues/5587 –

3

चेक बाहर इस एक: 3 डी अंतरिक्ष में माउस के चौराहे और घन से किसी के लिए

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

यह एक बहुत अच्छा समाधान है और एक सीपीयू-गहन रेएकास्ट को रोकता है, लेकिन केवल यह देखता है कि माउस ऑब्जेक्ट के पिवट के पास क्लिक करता है या नहीं । अवंतेज यह है कि जाल के बिना एक वस्तु इस तरह से काम करेगी। नुकसान परिपत्र "हॉटस्पॉट" है। – Hacky

2

चेकों और यह रंग है बदल देता है। शायद this आपकी मदद करता है।

+3

स्टैक ओवरफ़्लो में आपका स्वागत है! [कैसे जवाब दें] (http://stackoverflow.com/questions/how-to-answer) के माध्यम से पढ़ने के लिए एक मिनट लें - यह सहायक दिखता है लेकिन कोड के बारे में कुछ स्पष्टीकरण से इसका लाभ होगा, [संपादित करें] पर विचार करें (http://stackoverflow.com/posts/41385887/edit)- उसमें? –

0

मैं इसे कैनवास के लिए कार्यान्वित करने की कोशिश करने वाली समस्याओं में भाग गया जो स्क्रीन की पूरी चौड़ाई और ऊंचाई नहीं लेता है। यहां वह समाधान है जो मैंने पाया है काफी अच्छी तरह से काम करता है।

एक मौजूदा कैनवास पर सब कुछ प्रारंभ:

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), 
} 

कैनवास के लिए एक घटना श्रोता जोड़ें:

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) 

या एक 'touchstart' घटना के लिए, mouse.x की गणना लाइनों को बदलने और mouse.y में:

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; 
संबंधित मुद्दे