2013-08-31 21 views
11

Występuje trudność w wybieraniu obiektów za pomocą aparatu ortograficznego za pomocą funkcji raycaster. Chociaż nie mam z tym problemu, kiedy używam kamery perspektywicznej. Jedyne, co zmieniam podczas przełączania między nimi, to kamera typu.Kamera ortograficzna i zaznaczanie obiektów za pomocą raycast

Jestem w stanie wybrać twarze w widoku prostokątnym, ale jest to tylko luźno związane z tym, gdzie klikam na ekranie. Kiedy mogę kliknąć z dala od obiektu i nadal będzie on powracał, tak jakby uderzył w obiekt w pobliżu jego środka.

Jakieś pomysły na temat tego, czego tu brakuje?

Opieram większość mojego kodu na tym example i mam nadzieję, że uzyskam bardzo podobny wynik z mojego kodu. (Ten przykład mam przedstawieniu używa aparatu perspektywy)

Każda pomoc jest mile widziane

<html> 
<head> 
    <style> 
    canvas { 
     left: 0; 
     top: 0; 
     width: 100%; 
     height: 100%; 
     position: fixed; 
     background-color: #111115; 
    } 
    </style> 
</head> 
<body id='c'> 
    <script src="js/three.js"></script> 

    <script> 

    var obj = []; 
    var mouse ={}; 
    var zoom = 2; 

    var scene = new THREE.Scene(); 

    //switch between these two and see the difference: 
    //var camera = new THREE.OrthographicCamera(window.innerWidth/-zoom, window.innerWidth/zoom, window.innerHeight/zoom, window.innerHeight/-zoom, -1000, 1000); 
    var camera = new THREE.PerspectiveCamera(45, window.innerWidth/window.innerHeight, 1, 1000); 

    camera.position = new THREE.Vector3(100,100,100); 
    camera.lookAt(new THREE.Vector3(0,0,0)); 

    // this material causes a mesh to use colors assigned to faces 
    var material = new THREE.MeshBasicMaterial( 
    { color: 0xffffff, vertexColors: THREE.FaceColors }); 

    var sphereGeometry = new THREE.SphereGeometry(80, 32, 16); 
    for (var i = 0; i < sphereGeometry.faces.length; i++) 
    { 
     face = sphereGeometry.faces[ i ]; 
     face.color.setRGB(0, 0, 0.8 * Math.random() + 0.2);  
    } 
    obj['box'] = {}; 
    obj['box'] = new THREE.Mesh(sphereGeometry, material); 
    obj['box'].castShadow = true; 
    obj['box'].receiveShadow = true; 
    scene.add(obj['box']); 

    var ambientLight = new THREE.AmbientLight(0xbbbbbb); 
    scene.add(ambientLight); 

    var directionalLight = new THREE.DirectionalLight(0xffffff, 1); 
    directionalLight.position.set(-100, 40, 100); 
    directionalLight.castShadow = true; 
    directionalLight.shadowOnly = true; 
    directionalLight.shadowDarkness = .5; 
    scene.add(directionalLight); 

    var renderer = new THREE.WebGLRenderer(); 
    renderer.setSize(window.innerWidth, window.innerHeight); 
    renderer.shadowMapEnabled = true; 
    renderer.shadowMapSoft = true; 
    document.body.appendChild(renderer.domElement); 

    projector = new THREE.Projector(); 
    document.addEventListener('mousedown', onDocumentMouseDown, false); 
    function onDocumentMouseDown(event) { 
     // the following line would stop any other event handler from firing 
     // (such as the mouse's TrackballControls) 
     // event.preventDefault(); 

     console.log("Click."); 

     // update the mouse variable 
     mouse.x = (event.clientX/window.innerWidth) * 2 - 1; 
     mouse.y = - (event.clientY/window.innerHeight) * 2 + 1; 

     // find intersections 

     // create a Ray with origin at the mouse position 
     // and direction into the scene (camera direction) 
     var vector = new THREE.Vector3(mouse.x, mouse.y, 1); 
     projector.unprojectVector(vector, camera); 
     var ray = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize()); 

     // create an array containing all objects in the scene with which the ray intersects 
     var intersects = ray.intersectObjects([obj['box']]); 

     // if there is one (or more) intersections 
     if (intersects.length > 0) 
     { 
     console.log("Hit @ " + toString(intersects[0].point)); 
     console.log(intersects); 
     // change the color of the closest face. 
     intersects[ 0 ].face.color.setRGB(0.8 * Math.random() + 0.2, 0, 0); 
     intersects[ 0 ].object.geometry.colorsNeedUpdate = true; 
     } 
    } 

    function toString(v) { return "[ " + v.x + ", " + v.y + ", " + v.z + " ]"; } 

    var render = function() { 
     requestAnimationFrame(render); 
     renderer.render(scene, camera); 
    }; 

    console.log(camera); 
    console.log(obj['box']) 
    render(); 

    </script> 
</body> 

Mam nadzieję, że jest to coś proste, że ja po prostu nie wiem jeszcze.

Three.js r60

+1

Tip : Twoja "komora ortograficzna" w pobliżu "jest ujemna. To za kamerą. Powinno być pozytywne. Również pierwsze cztery argumenty są we współrzędnych światowych, a nie w pikselach, więc nie dajcie się pomylić. – WestLangley

Odpowiedz

18

Oto wzór do wykorzystania podczas ray casting albo z aparatu lub ortograficznych perspektywy kamery:

var raycaster = new THREE.Raycaster(); // create once 
var mouse = new THREE.Vector2(); // create once 

... 

mouse.x = (event.clientX/renderer.domElement.clientWidth) * 2 - 1; 
mouse.y = - (event.clientY/renderer.domElement.clientHeight) * 2 + 1; 

raycaster.setFromCamera(mouse, camera); 

var intersects = raycaster.intersectObjects(objects, recursiveFlag); 

Three.js r.84

+1

thx. niewygodne, że kod pobrania zależy od typu kamery. – KregHEk

+0

... ale znacznie lepiej niż w WebGL :) – potomek

+0

Dodaj konfigurację kamery, ponieważ przedstawiony fragment jest od niej zależny. –

0

Jeszcze jedna uwaga, że może zaoszczędzić ci kłopotów. Jeśli masz aparat tak:

var camera = new THREE.OrthographicCamera(0, window.innerWidth, -window.innerHeight, 0, -100, 100); 

wówczas podczas ray casting, należy przesunąć origin.z ray camera.far za to trafić coś w całym zakresie widzialnym:

this.ray.origin.set(0, 0, 0); 
this.camera.localToWorld(this.ray.origin); 
this.raycaster.setFromCamera(this.mouseCoord, this.camera); 
this.ray.origin.z = this.camera.far;