オブジェクトの選択


REVISION: '78'

デモ：http://codepen.io/mo4_9/pen/GqLjba

テストが終わり次第`mousemoveイベント`は削除

```javascript:click処理の抜粋(ES6)

class MyRaycaster {
    constructor(opts = {}) {
        this.tube = null;
        this.controls = this.getControls();
        this.init();
    }

    init () {
    
    	---（略）---

        document.addEventListener('mousedown', e => {
            this.onDocumentMouseDown(e);
        }, false);
        // テストが終わったら削除
        document.addEventListener('mousemove', e => {
            this.onDocumentMouseMove(e);
        }, false);
        
        ---（略）---

        this.getControls();
        this.setDatGUI();
        this.render();
    }

    getControls () {
        const controls = new function () {
            this.showRay = true;
        };
        return controls;
    }

    setDatGUI () {
        const gui = new dat.GUI();
        console.log(this.controls.showRay);
        gui.add(this.controls, 'showRay').onChange( (e) => {
            if (this.tube) this.scene.remove(this.tube)
        });
    }

    render () {
        this.renderer.render(this.scene, this.camera);
        requestAnimationFrame( () => {
            this.render();
        });
    }

    // クリックしたオブジェクトを取得
    onDocumentMouseDown(e) {

        const intersects = this.getIntersectObjects(e);

        if (intersects.length > 0) {

            console.log('intersects[0] : ', intersects[0]); // 最も近いオブジェクト
            console.log('distance : ', intersects[0].distance);
            console.log('vector3 : ', intersects[0].point.x + ", " + intersects[0].point.y + ", " + intersects[0].point.z); // 光線との交差座標

            intersects[0].object.material.transparent = true;
            intersects[0].object.material.opacity = 0.1;
        }
    }

    // raycastの補助線
    onDocumentMouseMove(e) {
        if (!this.controls.showRay) return;

        const intersects = this.getIntersectObjects(e);

        if (intersects.length > 0) {

            let points = [];

            points.push(new THREE.Vector3(this.startPointX, this.startPointY - 0.2, this.startPointZ));
            points.push(intersects[0].point);

            const mat = new THREE.MeshBasicMaterial({color: 0xff0000, transparent: true, opacity: 0.6});
            const tubeGeometry = new THREE.TubeGeometry(new THREE.CatmullRomCurve3(points), 60, 0.001);

            if (this.tube) this.scene.remove(this.tube);

            if (this.controls.showRay) {
                this.tube = new THREE.Mesh(tubeGeometry, mat);
                this.scene.add(this.tube);
            }
            console.log(points[1].x, points[1].y, points[1].z);
        }
    }

    // 光線と交わるオブジェクトを収集
    getIntersectObjects(e) {
        // クリックされた位置を元にVector3を生成
        let vector = new THREE.Vector3(
          ( e.clientX / window.innerWidth ) * 2 - 1,
          -( e.clientY / window.innerHeight ) * 2 + 1, 0.5);
        // Three.js内の座標に変換
        // スクリーン座標系からワールド座標系に逆射影
        vector.unproject(this.camera);

        // カメラからクリックされた位置まで光線を飛ばす
        const raycaster = new THREE.Raycaster( this.camera.position, vector.sub(this.camera.position).normalize() );

        // 光線と交わるオブジェクトの登録
        const intersects = raycaster.intersectObjects([this.sphere, this.cylinder, this.cube]);

        return intersects;
    }

}

const myRaycaster = new MyRaycaster();
```


> 参考
[初めてのThree.js 第2版――WebGLのためのJavaScript 3Dライブラリ](https://www.oreilly.co.jp/books/9784873117706/)
http://qiita.com/mo49/items/c8ca223fb90a8053f902