美文网首页
鼠标点击选中模型

鼠标点击选中模型

作者: Codifier | 来源:发表于2019-11-19 15:47 被阅读0次
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Select Object</title>
        <script src="../../three-part/threejs/three.js"></script>
        <script src="../../three-part/utils/stats.min.js"></script>
        <script src="../../three-part/utils/dat.gui.min.js"></script>
        <script src="../controls/TrackballControls.js"></script>
        <script src="../util/util.js"></script>
        <style>
            body {
                margin: 0;
                overflow: hidden;
            }
        </style>
    </head>
    <body>
    <div id="container"></div>
    <script type="text/javascript">
        init();
        function init() {
            // show FPS
            let stats = initStats();
            // resize
            window.addEventListener('resize', onResize, false);
            document.addEventListener('click', onDocumentMouseDown, false);
            document.addEventListener('mousemove', onDocumentMouseMove, false);
    
            let scene = new THREE.Scene();
            let camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
            camera.position.x = -30;
            camera.position.y = 40;
            camera.position.z = 30;
            camera.lookAt(scene.position);
    
            let renderer = new THREE.WebGLRenderer();
            renderer.setClearColor(new THREE.Color(0x000000));
            renderer.setSize(window.innerWidth, window.innerHeight);
            renderer.shadowMap.enabled = true;
            document.getElementById("container").appendChild(renderer.domElement);
    
            // init trackball control
            let trackballControls = initTrackballControls(camera, renderer);
            let clock = new THREE.Clock();
            let tube;
    
            // add a plane
            let planeGeometry = new THREE.PlaneGeometry(100, 100, 1, 1);
            let planeMaterial = new THREE.MeshLambertMaterial({
                color: 0xffffff
            });
            let plane = new THREE.Mesh(planeGeometry, planeMaterial);
            plane.receiveShadow = true;
            plane.rotation.x = -0.5 * Math.PI;
            scene.add(plane);
    
            // create a cube
            let cubeGeometry = new THREE.BoxGeometry(4, 4, 4);
            let cubeMaterial = new THREE.MeshStandardMaterial({color: 0xff0000});
            let cube = new THREE.Mesh(cubeGeometry, cubeMaterial);
            cube.castShadow = true;
            cube.position.set(-10, 4, 0);
            scene.add(cube);
    
            // create a sphere
            let sphereGeometry = new THREE.SphereGeometry(4, 20, 20);
            let sphereMaterial = new THREE.MeshStandardMaterial({color: 0x7777ff});
            let sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
            sphere.position.set(20, 5, 2);
            sphere.castShadow = true;
            scene.add(sphere);
    
            // create a cylinder
            let cylinderGeometry = new THREE.CylinderGeometry(2, 2, 20);
            let cylinderMaterial = new THREE.MeshStandardMaterial({color: 0x77ff77});
            let cylinder = new THREE.Mesh(cylinderGeometry, cylinderMaterial);
            cylinder.castShadow = true;
            cylinder.position.set(0, 5, 1);
            scene.add(cylinder);
    
            let ambienLight = new THREE.AmbientLight(0x353535, 3);
            scene.add(ambienLight);
    
            // attributes which can be modified in GUI
            const controls = {
                "showRay" : false
            };
            // init GUI
            initGUI();
    
            renderScene();
    
            function initGUI(){
                let gui = new dat.GUI();
                gui.add(controls, 'showRay').onChange(function (e) {
                    if (tube) scene.remove(tube)
                });
            }
    
            function onResize() {
                camera.aspect = window.innerWidth / window.innerHeight;
                camera.updateProjectionMatrix();
                renderer.setSize(window.innerWidth, window.innerHeight);
            }
    
            function onDocumentMouseDown(event) {
                let vector = new THREE.Vector3((event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window.innerHeight) * 2 + 1, 0.5);
                // Unprojects the vector with the camera's projection matrix.
                vector = vector.unproject(camera);
    
                /**
                 * Raycaster( origin : Vector3, direction : Vector3, near : Float, far : Float ) {
                 * origin — The origin vector where the ray casts from.
                 * direction — The direction vector that gives direction to the ray. Should be normalized.
                 * near — All results returned are further away than near. Near can't be negative. Default value is 0.
                 * far — All results returned are closer than far. Far can't be lower than near. Default value is Infinity.
                 * @type {Raycaster}
                 */
                let raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
                /**
                 * intersectObjects ( objects : Array, recursive : Boolean, optionalTarget : Array )
                 * objects — The objects to check for intersection with the ray.
                 * recursive — If true, it also checks all descendants of the objects. Otherwise it only checks intersection with the objects. Default is false.
                 * optionalTarget — (optional) target to set the result. Otherwise a new Array is instantiated. If set, you must clear this array prior to each call (i.e., array.length = 0;).
                 * Checks all intersection between the ray and the objects with or without the descendants.
                 * Intersections are returned sorted by distance, closest first.
                 */
                let intersects = raycaster.intersectObjects([sphere, cylinder, cube]);
    
                if (intersects.length > 0) {
                    intersects[0].object.material.transparent = true;
                    intersects[0].object.material.opacity = 0.1;
                }
            }
    
            function onDocumentMouseMove(event) {
                if (controls.showRay) {
                    let vector = new THREE.Vector3((event.clientX / window.innerWidth) * 2 - 1, -(event.clientY / window.innerHeight) * 2 + 1, 0.5);
                    vector = vector.unproject(camera);
    
                    let raycaster = new THREE.Raycaster(camera.position, vector.sub(camera.position).normalize());
                    let intersects = raycaster.intersectObjects([sphere, cylinder, cube]);
    
                    if (intersects.length > 0) {
                        let points = [];
                        points.push(new THREE.Vector3(-30, 39.8, 30));
                        points.push(intersects[0].point);
    
                        let mat = new THREE.MeshBasicMaterial({color: 0xff0000, transparent: true, opacity: 0.6});
                        /**
                         * TubeGeometry(path : Curve, tubularSegments : Integer, radius : Float, radialSegments : Integer, closed : Boolean)
                         * path — Curve - A path that inherits from the Curve base class
                         * tubularSegments — Integer - The number of segments that make up the tube, default is 64
                         * radius — Float - The radius of the tube, default is 1
                         * radialSegments — Integer - The number of segments that make up the cross-section, default is 8
                         * closed — Boolean Is the tube open or closed, default is false
                         *
                         * CatmullRomCurve3( points : Array, closed : Boolean, curveType : String, tension : Float )
                         * points – An array of Vector3 points
                         * closed – Whether the curve is closed. Default is false.
                         * curveType – Type of the curve. Default is centripetal.
                         * tension – Tension of the curve. Default is 0.5.
                         * @type {TubeGeometry}
                         */
                        let tubeGeometry = new THREE.TubeGeometry(new THREE.CatmullRomCurve3(points), 60, 0.001);
    
                        if (tube) scene.remove(tube);
    
                        if (controls.showRay) {
                            tube = new THREE.Mesh(tubeGeometry, mat);
                            scene.add(tube);
                        }
                    }
                }
            }
    
            function renderScene(){
                trackballControls.update(clock.getDelta());
                stats.update();
                requestAnimationFrame(renderScene);
                renderer.render(scene, camera);
            }
        }
    </script>
    </body>
    </html>
    

    运行结果:

    1. 选中模型:


    2. 显示射线:


    相关文章

      网友评论

          本文标题:鼠标点击选中模型

          本文链接:https://www.haomeiwen.com/subject/oszwictx.html