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

鼠标点击选中模型

作者: 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