鼠標拾取(光線拾取)

作者:桑榆
QQ:934440653
有問題,評論留言,或qq聯繫

案例效果

鼠標拾取

主要代碼

1.創建矩形

(1)6-8行限制隨機產生的矩形的長、寬、縱深不超過20;
(2)14-16行限制隨機產生的矩形在一個長、寬、縱深爲600的包圍盒內,以(0,0,0)爲分割點,所以減300;座標在x,y,z(-300,300)之間。
(3)20-22行讓創建的矩形有一定旋轉度

         var BoundingBoxLength = 600; //規定隨機創建的矩形,在半徑爲300的包圍盒內
        function initObject(){ //創建2000個矩形

            for(var i = 0; i < 2000 ; i++){
                //隨機產生不同大小的矩形
                var cubeX = Math.random() * 20;
                var cubeY = Math.random() * 20;
                var cubeZ = Math.random() * 20;
                var geometry = new THREE.CubeGeometry(cubeX,cubeY,cubeZ);
                var material = new THREE.MeshLambertMaterial({color:Math.random() * 0xffffff}); //隨機產生一個顏色
                var cube = new THREE.Mesh(geometry,material);

                //隨機產生矩形的位置
                var cubePositionX = Math.random() * 600 - 300;
                var cubePositionY = Math.random() * 600 - 300;
                var cubePositionZ = Math.random() * 600 - 300;
                cube.position.set(cubePositionX,cubePositionY,cubePositionZ);

                //隨機產生矩形的旋轉方式
                cube.rotation.x = Math.random() * 2 * Math.PI;
                cube.rotation.y = Math.random() * 2 * Math.PI;
                cube.rotation.z = Math.random() * 2 * Math.PI;

                scene.add(cube);
            }
            
        }

相機旋轉

(1)1行設置相機的半徑,以這個半徑旋轉
(2)2行爲相機的初始經緯座標(0,0);
(3)6-7經緯座標每次渲染遞增0.01°(遞增太大,旋轉太快);
(4)8-9行設置轉換後的相機座標
(5)10行始終相機看向場景的中心
(6)更新相機,相機的參數改變後一定更新,切記!!!!!

        var cameraRadius = 400;//相機的旋轉半徑
        var cameraLongitude = 0 ,cameraLatitude = 0; //相機的經緯度座標
        function animate(){
            requestAnimationFrame(animate);
            
            cameraLongitude += 0.1;
            cameraLatitude += 0.1;
            var cameraPosition = getPosition(cameraLongitude,cameraLatitude,cameraRadius);
            camera.position.set(cameraPosition.x ,cameraPosition.y,cameraPosition.z);
            camera.lookAt(scene.position);
            camera.updateProjectionMatrix();

            renderer.render(scene,camera);
        }

經緯度座標轉換爲三維座標

將標記地點經緯度座標與三維x,y,z座標轉換方法。


        function getPosition (longitude, latitude, radius) {
            // 經緯度轉換函數,longitude表示經度,latitude表示維度,radius表示球體半徑
            // 將經度,緯度轉換爲rad座標 
            var lg = THREE.Math.degToRad(longitude);
            var lt = THREE.Math.degToRad(latitude);
            var temp = radius * Math.cos(lt);
            // 獲取x,y,z座標
            var x = temp * Math.sin(lg);
            var y = radius * Math.sin(lt);
            var z = temp * Math.cos(lg);
            return {
                x: x,
                y: y,
                z: z
            }
        }

鼠標拾取

       //鼠標拾取
        function mouseRaycaster(){ 
            dom.addEventListener('click',clickEvent,false);
            function clickEvent(event){
                event.preventDefault();
                // 聲明 raycaster 和 mouse 變量
                var raycaster = new THREE.Raycaster(); // 光線投射用於進行鼠標拾取(在三維空間中計算出鼠標移過了什麼物體)。
                var mouse = new THREE.Vector2();       //存放鼠標點擊座標

                // 通過鼠標點擊位置,計算出 raycaster 所需點的位置,以屏幕爲中心點,範圍 -1 到 1
                mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
                mouse.y = -(event.clientY / window.innerHeight) * 2 + 1

                // 通過攝像機和鼠標位置更新射線  由相機照向鼠標(交點即爲鼠標點擊的點)
                raycaster.setFromCamera( mouse, camera,0,1000);

                var INTERSCTSColor = [];
                // 計算物體和射線的焦點 在場景中找到相機和鼠標相交的對象放在intersects這個數組中  射線穿過的物體可能有多個
                var intersects = raycaster.intersectObjects( scene.children );
                for ( var i = 0; i < intersects.length; i++ ) {
                    INTERSCTSColor.push(intersects[ i ].object.material.color);
                    intersects[ i ].object.material.color.set( 0xff0000 ); //將射線穿過的物體全部改變顏色
                }
            }
        }

完整代碼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>鼠標拾取</title>
    <style>
    *{
            padding: 0;
            margin: 0;
        }
        html,body{
            height: 100%;
            width: 100%;
        }
        #webGL{
            height: 100%;
            width: 100%;
        }
    </style>
</head>
<body>
    <script src="../buildJs/build/three105.js"></script>
    <div id="webGL"></div>
    <script>
        var renderer,dom,domWidth,domHeight;
        function initRender(){
            dom = document.getElementById('webGL');
            domWidth = dom.clientWidth;
            domHeight = dom.clientHeight;

            renderer = new THREE.WebGLRenderer({antialias:true});
            renderer.setSize(domWidth,domHeight);
            renderer.setPixelRatio(window.devicePixelRatio);

            dom.appendChild(renderer.domElement);
            renderer.setClearColor(0xFFFFFF,1.0);
        }

        var scene;
        function initScene(){
            scene = new THREE.Scene();
            scene.background = new THREE.Color(0xcfcfcf);
        }

        var ambientLight,directionalLight;
        function initLight(){
            ambientLight = new THREE.AmbientLight(0x404040,1.0);
            scene.add(ambientLight);

            directionalLight = new THREE.DirectionalLight(0xffffff,0.8);
            directionalLight.lookAt(new THREE.Vector3(0,0,0));
            directionalLight.position.set(-600,600,600);
            scene.add(directionalLight);
        }
        

        var camera;
        function initCamera(){
            camera = new THREE.PerspectiveCamera(45,window.innerWidth / window.innerHeight,1,1000);
            camera.position.set(0,300,500);
            camera.lookAt(scene.position);
            scene.add(camera);
        }

        var cameraRadius = 400;//相機的旋轉半徑
        var cameraLongitude = 0 ,cameraLatitude = 0; //相機的經緯度座標
        function animate(){
            requestAnimationFrame(animate);
            
            cameraLongitude += 0.1;
            cameraLatitude += 0.1;
            var cameraPosition = getPosition(cameraLongitude,cameraLatitude,cameraRadius);
            camera.position.set(cameraPosition.x ,cameraPosition.y,cameraPosition.z);
            camera.lookAt(scene.position);
            camera.updateProjectionMatrix();
            
            mouseRaycaster();

            renderer.render(scene,camera);
        }

        function listenWindow(){  //監聽屏幕寬高變化
            window.addEventListener('resize',onWindowResize,false);
            function onWindowResize(){
                domWidth = window.innerWidth;
                domHeight = window.innerHeight;
                camera.aspect = domWidth / domHeight;
                camera.updateProjectionMatrix();
                renderer.setSize(domWidth, domHeight); //設置渲染器大小,即canvas畫布的大小
            }
        }

        var BoundingBoxLength = 600; //規定隨機創建的矩形,在半徑爲300的包圍盒內
        function initObject(){ //創建2000個矩形

            for(var i = 0; i < 2000 ; i++){
                //隨機產生不同大小的矩形
                var cubeX = Math.random() * 20;
                var cubeY = Math.random() * 20;
                var cubeZ = Math.random() * 20;
                var geometry = new THREE.CubeGeometry(cubeX,cubeY,cubeZ);
                var material = new THREE.MeshLambertMaterial({color:Math.random() * 0xffffff}); //隨機產生一個顏色
                var cube = new THREE.Mesh(geometry,material);

                //隨機產生矩形的位置
                var cubePositionX = Math.random() * 600 - 300;
                var cubePositionY = Math.random() * 600 - 300;
                var cubePositionZ = Math.random() * 600 - 300;
                cube.position.set(cubePositionX,cubePositionY,cubePositionZ);

                //隨機產生矩形的旋轉方式
                cube.rotation.x = Math.random()  * Math.PI;
                cube.rotation.y = Math.random()  * Math.PI;
                cube.rotation.z = Math.random()  * Math.PI;

                scene.add(cube);
            }
            
        }


        //將標記地點經緯度座標與三維x,y,z座標轉換方法。
        function getPosition (longitude, latitude, radius) {
            // 經緯度轉換函數,longitude表示經度,latitude表示維度,radius表示球體半徑
            // 將經度,緯度轉換爲rad座標 
            var lg = THREE.Math.degToRad(longitude);
            var lt = THREE.Math.degToRad(latitude);
            var temp = radius * Math.cos(lt);
            // 獲取x,y,z座標
            var x = temp * Math.sin(lg);
            var y = radius * Math.sin(lt);
            var z = temp * Math.cos(lg);
            return {
                x: x,
                y: y,
                z: z
            }
        }

        //鼠標拾取
        function mouseRaycaster(){ 
            dom.addEventListener('click',clickEvent,false);
            function clickEvent(event){
                event.preventDefault();
                // 聲明 raycaster 和 mouse 變量
                var raycaster = new THREE.Raycaster(); // 光線投射用於進行鼠標拾取(在三維空間中計算出鼠標移過了什麼物體)。
                var mouse = new THREE.Vector2();       //存放鼠標點擊座標

                // 通過鼠標點擊位置,計算出 raycaster 所需點的位置,以屏幕爲中心點,範圍 -1 到 1
                mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
                mouse.y = -(event.clientY / window.innerHeight) * 2 + 1

                // 通過攝像機和鼠標位置更新射線  由相機照向鼠標(交點即爲鼠標點擊的點)
                raycaster.setFromCamera( mouse, camera,0,1000);

                var INTERSCTSColor = [];
                // 計算物體和射線的焦點 在場景中找到相機和鼠標相交的對象放在intersects這個數組中  射線穿過的物體可能有多個
                var intersects = raycaster.intersectObjects( scene.children );
                for ( var i = 0; i < intersects.length; i++ ) {
                    INTERSCTSColor.push(intersects[ i ].object.material.color);
                    intersects[ i ].object.material.color.set( 0xff0000 ); //將射線穿過的物體全部改變顏色
                }
            }
        }

        initRender();
        initScene();
        initCamera();
        initLight();
        listenWindow();
        initObject();
        animate();
    </script>
</body>
</html>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章