threeJS創建mesh,創建平面,設置mesh的平移,旋轉、縮放、自傳、透明度、拉伸


這個小案例是當初我在學習的時候,小的一個小案例,代碼還需要進一步優化;還請諒解~~;主要用到了threeJS創建mesh,創建平面,設置mesh的平移,旋轉、縮放、自傳、透明度、拉伸等這些小功能;

(點擊每個mesh,mesh的顏色會變為紅色)

點擊

1  需要加載這些相關的js文件

2   下面是實現的一些小功能

3   下面是相關代碼,代碼還沒有優化,請諒解~~(具體的每一個小功能后面我都會進行一一講解)

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title></title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
            /* 隱藏body窗口區域滾動條 */
        }
    </style>
    <!--引入three.js三維引擎-->
    <script src="js/three.js"></script>
    <!-- 引入threejs擴展控件OrbitControls.js -->
    <script src="js/OrbitControls.js"></script>
    <script src="js/stats.min.js"></script>
    <script src="js/jquery-1.9.0.js"></script>
    <script src="js/dat.gui.js"></script>
    <script src="js/stats.js"></script>
</head>
<body>
    <div id="Stats-output">
    </div>
    <div id="WebGL-output">
    </div>
    <script type="text/javascript">

        // once everything is loaded, we run our Three.js stuff.
        $(function () {

            var stats = initStats();

            // create a scene, that will hold all our elements such as objects, cameras and lights.
            var scene = new THREE.Scene();

            // create a camera, which defines where we're looking at.
            var camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);

            // create a render and set the size
            var renderer;
            var webGLRenderer = new THREE.WebGLRenderer();
            webGLRenderer.setClearColorHex(0xEEEEEE, 1.0);
            webGLRenderer.setSize(window.innerWidth, window.innerHeight);
            webGLRenderer.shadowMapEnabled = true;

            var canvasRenderer = new THREE.CanvasRenderer();
            canvasRenderer.setSize(window.innerWidth, window.innerHeight);
            renderer = webGLRenderer;

            var groundGeom = new THREE.PlaneGeometry(100, 100, 4, 4);
            var groundMesh = new THREE.Mesh(groundGeom, new THREE.MeshBasicMaterial({ color: 0x777777 }));
            groundMesh.rotation.x = -Math.PI / 2;
            groundMesh.position.y = -20;
            scene.add(groundMesh);

            var sphereGeometry = new THREE.SphereGeometry(14, 20, 20);
            var cubeGeometry = new THREE.CubeGeometry(15, 15, 15);
            var planeGeometry = new THREE.PlaneGeometry(14, 14, 4, 4);


            var meshMaterial = new THREE.MeshNormalMaterial({ color: 0x7777ff });
            var sphere = new THREE.Mesh(sphereGeometry, meshMaterial);
            var cube = new THREE.Mesh(cubeGeometry, meshMaterial);
            var plane = new THREE.Mesh(planeGeometry, meshMaterial);

            // position the sphere
            sphere.position.x = 0;
            sphere.position.y = 3;
            sphere.position.z = 2;

            for (var f = 0, fl = sphere.geometry.faces.length; f < fl; f++) {
                var face = sphere.geometry.faces[f];
                var arrow = new THREE.ArrowHelper(
                    face.normal,
                    face.centroid,
                    2,
                    0x3333FF);
                sphere.add(arrow);
            }


            cube.position = sphere.position;
            plane.position = sphere.position;


            // add the sphere to the scene
            scene.add(cube);

            // position and point the camera to the center of the scene
            camera.position.x = -20;
            camera.position.y = 30;
            camera.position.z = 40;
            camera.lookAt(new THREE.Vector3(10, 0, 0));

            // add subtle ambient lighting
            var ambientLight = new THREE.AmbientLight(0x0c0c0c);
            scene.add(ambientLight);

            // add spotlight for the shadows
            var spotLight = new THREE.SpotLight(0xffffff);
            spotLight.position.set(-40, 60, -10);
            spotLight.castShadow = true;
            scene.add(spotLight);

            // add the output of the renderer to the html element
            $("#WebGL-output").append(renderer.domElement);

            // call the render function
            var step = 0;
            var oldContext = null;

            var controls = new function () {
                this.rotationSpeed = 0.02;
                this.bouncingSpeed = 0.03;

                this.opacity = meshMaterial.opacity;
                this.transparent = meshMaterial.transparent;

                this.visible = meshMaterial.visible;
                this.side = "front";

                this.wireframe = meshMaterial.wireframe;
                this.wireframeLinewidth = meshMaterial.wireframeLinewidth;

                this.selectedMesh = "cube";

                this.shadow = "flat";

            }

            var gui = new dat.GUI();


            var spGui = gui.addFolder("Mesh");
            spGui.add(controls, 'opacity', 0, 1).onChange(function (e) {
                meshMaterial.opacity = e
            });
            spGui.add(controls, 'transparent').onChange(function (e) {
                meshMaterial.transparent = e
            });
            spGui.add(controls, 'wireframe').onChange(function (e) {
                meshMaterial.wireframe = e
            });
            spGui.add(controls, 'wireframeLinewidth', 0, 20).onChange(function (e) {
                meshMaterial.wireframeLinewidth = e
            });
            spGui.add(controls, 'visible').onChange(function (e) {
                meshMaterial.visible = e
            });
            spGui.add(controls, 'side', ["front", "back", "double"]).onChange(function (e) {
                console.log(e);
                switch (e) {
                    case "front":
                        meshMaterial.side = THREE.FrontSide;
                        break;
                    case "back":
                        meshMaterial.side = THREE.BackSide;
                        break;
                    case "double":
                        meshMaterial.side = THREE.DoubleSide
                        break;
                }
                meshMaterial.needsUpdate = true;

            });
            spGui.add(controls, 'shadow', ["flat", "smooth"]).onChange(function (e) {
                switch (e) {
                    case "flat":
                        // https://github.com/mrdoob/three.js/issues/1929
                        meshMaterial.shading = THREE.FlatShading;
                        break;
                    case "smooth":
                        meshMaterial.shading = THREE.SmoothShading;
                        break;
                }

                var oldPos = sphere.position.clone();
                scene.remove(sphere);
                scene.remove(plane);
                scene.remove(cube);
                sphere = new THREE.Mesh(sphere.geometry.clone(), meshMaterial);
                cube = new THREE.Mesh(cube.geometry.clone(), meshMaterial);
                plane = new THREE.Mesh(plane.geometry.clone(), meshMaterial);

                sphere.position = oldPos;
                cube.position = oldPos;
                plane.position = oldPos;

                switch (controls.selectedMesh) {
                    case "cube":
                        scene.add(cube);

                        break;
                    case "sphere":
                        scene.add(sphere);

                        break;
                    case "plane":
                        scene.add(plane);
                        break;

                }

                meshMaterial.needsUpdate = true;
                console.log(meshMaterial);
            });

            spGui.add(controls, 'selectedMesh', ["cube", "sphere", "plane"]).onChange(function (e) {

                scene.remove(plane);
                scene.remove(cube);
                scene.remove(sphere);


                switch (e) {
                    case "cube":
                        scene.add(cube);

                        break;
                    case "sphere":
                        scene.add(sphere);

                        break;
                    case "plane":
                        scene.add(plane);
                        break;

                }

                scene.add(e);
            });

            render();

            function render() {
                stats.update();

                cube.rotation.y = step += 0.01;
                plane.rotation.y = step;
                sphere.rotation.y = step;


                // render using requestAnimationFrame
                requestAnimationFrame(render);
                renderer.render(scene, camera);
            }

            function initStats() {

                var stats = new Stats();

                stats.setMode(0); // 0: fps, 1: ms


                // Align top-left
                stats.domElement.style.position = 'absolute';
                stats.domElement.style.left = '0px';
                stats.domElement.style.top = '0px';

                $("#Stats-output").append(stats.domElement);

                return stats;
            }
        });


    </script>
    <script>
        /**
         * 創建場景對象Scene
         */
        var scene = new THREE.Scene();
        /**
         * 創建網格模型
         */
        //創建第一個方塊
        var geometry = new THREE.BoxGeometry(100, 100, 100); //創建一個立方體幾何對象Geometry
        var material = new THREE.MeshLambertMaterial({
            color: 0x0000ff
        }); //材質對象Material
        var mesh = new THREE.Mesh(geometry, material); //網格模型對象Mesh
        scene.add(mesh); //網格模型添加到場景中
        // 設置產生投影的網格模型
        mesh.castShadow = true;

        //創建第二個方塊
        var geometry2 = new THREE.BoxGeometry(100, 100, 100); //創建一個立方體幾何對象Geometry
        var material2 = new THREE.MeshLambertMaterial({
            color: 0x0000ff
        }); //材質對象Material
        var mesh2 = new THREE.Mesh(geometry2, material2); //網格模型對象Mesh
        mesh2.translateY(200);//方塊二沿y軸正方向平移40
        scene.add(mesh2); //網格模型添加到場景中

        //創建第三個方塊
        var geometry3 = new THREE.BoxGeometry(100, 100, 100); //創建一個立方體幾何對象Geometry
        var material3 = new THREE.MeshLambertMaterial({
            color: 0x0000ff,
            transparent: true,//開啟透明度
            opacity: 0.5,//設置透明度具體值
        }); //材質對象Material
        var mesh3 = new THREE.Mesh(geometry3, material3); //網格模型對象Mesh
        mesh3.translateY(400);//方塊二沿y軸正方向平移80
        scene.add(mesh3); //網格模型添加到場景中

        //創建第四個方塊
        var geometry4 = new THREE.BoxGeometry(100, 100, 100); //創建一個立方體幾何對象Geometry
        var material4 = new THREE.MeshLambertMaterial({
            color: 0x0000ff,
            transparent: true,//開啟透明度
            opacity: 0.5,//設置透明度具體值
        }); //材質對象Material
        var mesh4 = new THREE.Mesh(geometry4, material4); //網格模型對象Mesh
        mesh4.translateY(600);//方塊二沿y軸正方向平移120
        scene.add(mesh4); //網格模型添加到場景中

        //創建第五個方塊
        var geometry5 = new THREE.BoxGeometry(100, 100, 100); //創建一個立方體幾何對象Geometry
        var material5 = new THREE.MeshLambertMaterial({
            color: 0x0000ff
        }); //材質對象Material
        var mesh5 = new THREE.Mesh(geometry5, material5); //網格模型對象Mesh
        mesh5.translateY(800);//方塊二沿y軸正方向平移160
        scene.add(mesh5); //網格模型添加到場景中

        //創建第六個方塊
        var geometry6 = new THREE.BoxGeometry(100, 100, 100); //創建一個立方體幾何對象Geometry
        var material6 = new THREE.MeshLambertMaterial({
            color: 0x0000ff
        }); //材質對象Material
        var mesh6 = new THREE.Mesh(geometry6, material6); //網格模型對象Mesh
        mesh6.translateX(200);//方塊二沿y軸正方向平移40
        scene.add(mesh6); //網格模型添加到場景中
        mesh6.castShadow = true;

        //創建第七個方塊
        var geometry7 = new THREE.BoxGeometry(100, 100, 100); //創建一個立方體幾何對象Geometry
        var material7 = new THREE.MeshLambertMaterial({
            color: 0x0000ff
        }); //材質對象Material
        var mesh7 = new THREE.Mesh(geometry7, material7); //網格模型對象Mesh
        mesh7.translateX(400);//方塊二沿y軸正方向平移80
        scene.add(mesh7); //網格模型添加到場景中
        mesh7.castShadow = true;

        //創建第八個方塊
        var geometry8 = new THREE.BoxGeometry(100, 100, 100); //創建一個立方體幾何對象Geometry
        var material8 = new THREE.MeshLambertMaterial({
            color: 0x0000ff
        }); //材質對象Material
        var mesh8 = new THREE.Mesh(geometry8, material8); //網格模型對象Mesh
        mesh8.translateX(600);//方塊二沿y軸正方向平移120
        scene.add(mesh8); //網格模型添加到場景中
        mesh8.castShadow = true;

        //創建第九個方塊
        var geometry9 = new THREE.BoxGeometry(100, 100, 100); //創建一個立方體幾何對象Geometry
        var material9 = new THREE.MeshLambertMaterial({
            color: 0x0000ff
        }); //材質對象Material
        var mesh9 = new THREE.Mesh(geometry9, material9); //網格模型對象Mesh
        mesh9.translateX(800);//方塊二沿y軸正方向平移160
        scene.add(mesh9); //網格模型添加到場景中
        mesh9.castShadow = true;

        //創建第十個方塊
        var geometry10 = new THREE.BoxGeometry(200, 200, 200); //創建一個立方體幾何對象Geometry
        var material10 = new THREE.MeshLambertMaterial({
            color: 0x0000ff
        }); //材質對象Material
        var newMesh = new THREE.Mesh(geometry10, material10); //網格模型對象Mesh
        newMesh.copy(mesh);
        //相比mesh而言,在平移
        newMesh.translateX(-500);//方塊二沿y軸正方向平移300
        scene.add(newMesh); //網格模型添加到場景中

        // 通過Path類的線條繪制方法方法定義輪廓
        var shape = new THREE.Shape();
        shape.moveTo(0, 0); //起點
        shape.lineTo(0, 100); //第2點
        shape.lineTo(100, 100); //第3點
        shape.lineTo(100, 0); //第4點
        shape.lineTo(0, 0); //第5點
        var geometry11 = new THREE.ExtrudeGeometry( //拉伸造型
            shape, //二維輪廓
            //拉伸參數
            {
                amount: 300, //拉伸長度
            }
        );
        var material11 = new THREE.MeshPhongMaterial({
            color: 0x0000ff,
            side: THREE.DoubleSide, //兩面可見
            // wireframe: true,
        }); //材質對象
        var mesh11 = new THREE.Mesh(geometry11, material11); //網格模型對象
        mesh11.translateY(-500);//方塊二沿y軸正方向平移40
        scene.add(mesh11); //網格模型添加到場景中


        // 輔助坐標系
        var axisHelper = new THREE.AxisHelper(250);
        scene.add(axisHelper);

        /**
         * 光源設置
         */
        //點光源
        var point = new THREE.PointLight(0xffffff);
        point.position.set(40, 40, 30); //點光源位置
        scene.add(point); //點光源添加到場景中
        //環境光
        var ambient = new THREE.AmbientLight(0x444444);
        scene.add(ambient);

        //創建一個平面幾何體作為投影面
        var planeGeometry = new THREE.PlaneGeometry(2000, 2000);
        var planeMaterial = new THREE.MeshLambertMaterial({
            color: 0x999999
        }); //材質對象Material

        // 平面網格模型作為投影面
        var planeMesh = new THREE.Mesh(planeGeometry, planeMaterial); //網格模型對象Mesh
        scene.add(planeMesh); //網格模型添加到場景中
        planeMesh.rotateX(-Math.PI / 2); //旋轉網格模型
        planeMesh.position.y = -50; //設置網格模型y坐標
        // 設置接收陰影的投影面
        planeMesh.receiveShadow = true;

        // 方向光
        var directionalLight = new THREE.DirectionalLight(0xffffff, 1);
        // 設置光源位置
        directionalLight.position.set(60, 60, 60);
        scene.add(directionalLight);
        // 設置用於計算陰影的光源對象
        directionalLight.castShadow = true;
        // 設置計算陰影的區域,最好剛好緊密包圍在對象周圍
        // 計算陰影的區域過大:模糊  過小:看不到或顯示不完整
        directionalLight.shadow.camera.near = 0.5;
        directionalLight.shadow.camera.far = 300;
        directionalLight.shadow.camera.left = -50;
        directionalLight.shadow.camera.right = 50;
        directionalLight.shadow.camera.top = 200;
        directionalLight.shadow.camera.bottom = -100;
        // 設置mapSize屬性可以使陰影更清晰,不那么模糊
        // directionalLight.shadow.mapSize.set(1024,1024)
        console.log(directionalLight.shadow.camera);

        /**
         * 相機設置
         */
        var width = window.innerWidth; //窗口寬度
        var height = window.innerHeight; //窗口高度
        var k = width / height; //窗口寬高比
        var s = 1000; //三維場景顯示范圍控制系數,系數越大,顯示的范圍越大
        //創建相機對象
        var camera = new THREE.OrthographicCamera(-s * k, s * k, s, -s, 1, 2000);
        camera.position.set(200, 300, 200); //設置相機位置
        camera.lookAt(scene.position); //設置相機方向(指向的場景對象)

        //實現相機切換
        this.switchCamera = function () {
            if (camera instanceof THREE.PerspectiveCamera) {
                camera = new THREE.OrthographicCamera(window.innerWidth / -16, window.innerWidth / 16, window.innerHeight / 16, window.innerHeight / -16, -200, 500);
                camera.position.x = 120;
                camera.position.y = 60;
                camera.position.z = 180;
                camera.lookAt(scene.position);
                this.perspective = "Orthographic";
            } else {
                camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000);
                camera.position.x = 120;
                camera.position.y = 60;
                camera.position.z = 180;

                camera.lookAt(scene.position);
                this.perspective = "Perspective";
            }
        };//代碼放入GUI工具中,可以在頁面上動態切換相機


        //聲明raycaster和mouse變量
        var raycaster = new THREE.Raycaster();
        console.log(raycaster);
        var mouse = new THREE.Vector2();

        function onMouseClick(event) {

            //通過鼠標點擊的位置計算出raycaster所需要的點的位置,以屏幕中心為原點,值的范圍為-1到1.

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

            // 通過鼠標點的位置和當前相機的矩陣計算出raycaster
            raycaster.setFromCamera(mouse, camera);

            // 獲取raycaster直線和所有模型相交的數組集合
            var intersects = raycaster.intersectObjects(scene.children);
            console.log(intersects[i].object);
            console.log(intersects);

            //將所有的相交的模型的顏色設置為紅色,如果只需要將第一個觸發事件,那就數組的第一個模型改變顏色即可
            for (var i = 0; i < intersects.length; i++) {
                //ransparent: true;//開啟透明度
                //acity: 0.5//設置透明度具體值
                intersects[i].object.material.color.set(0xff0000);
                // console.log(intersects[i].object);
                // 因為sphereMaterial.opacity和sphere.material.opacity值是相等的,所以只判斷一個
                // if (sphereMaterial.opacity > 0) {
                //     sphereMaterial.opacity -= 0.05;
                //     sphere.material.opacity -= 0.05;
                // }
                // else {
                //     sphere.material.transparent = true;
                //     clearInterval(timer);
                // }

            }
        }

        window.addEventListener('click', onMouseClick, false);

        //初始化dat.GUI簡化試驗流程
        var gui;

        function initGui() {
            //聲明一個保存需求修改的相關數據的對象
            controls = {

            };

            var gui = new dat.GUI();

        }

        //初始化性能插件
        var stats;

        function initStats() {
            stats = new Stats();
            document.body.appendChild(stats.dom);
        }

        //用戶交互插件 鼠標左鍵按住旋轉,右鍵按住平移,滾輪縮放
        var controls;

        function initControls() {
            controls = new THREE.OrbitControls(camera, renderer.domElement);
            // 如果使用animate方法時,將此函數刪除
            //controls.addEventListener( 'change', render );
            // 使動畫循環使用時阻尼或自轉 意思是否有慣性
            controls.enableDamping = true;
            //動態阻尼系數 就是鼠標拖拽旋轉靈敏度
            //controls.dampingFactor = 0.25;
            //是否可以縮放
            controls.enableZoom = true;
            //是否自動旋轉
            controls.autoRotate = false;
            //設置相機距離原點的最遠距離
            controls.minDistance = 50;
            //設置相機距離原點的最遠距離
            controls.maxDistance = 1000;
            //是否開啟右鍵拖拽
            controls.enablePan = true;
        }

        //窗口變動觸發的函數
        function onWindowResize() {

            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            render();
            renderer.setSize(window.innerWidth, window.innerHeight);

        }

        function animate() {
            //更新控制器
            render();

            //更新性能插件
            stats.update();

            //controls.update();

            requestAnimationFrame(animate);
        }

        function draw() {
            initGui();
            initControls();
            initStats();
            animate();
            window.onresize = onWindowResize;
        }


        /**
         * 創建渲染器對象
         */
        var renderer = new THREE.WebGLRenderer({ antialias: true, alpha: true });
        renderer.setSize(width, height);//設置渲染區域尺寸
        renderer.setClearColor(0xb9d3ff, 1); //設置背景顏色
        renderer.shadowMapEnabled = true;
        document.body.appendChild(renderer.domElement); //body元素中插入canvas對象
        scene.add(ambient);
        //執行渲染操作   指定場景、相機作為參數
        renderer.render(scene, camera);
        // 渲染函數
        function render() {
            renderer.render(scene, camera); //執行渲染操作
            mesh8.rotateY(0.01);//每次繞y軸旋轉0.01弧度
            requestAnimationFrame(render); //請求再次執行渲染函數render,渲染下一幀
        }
        render();

        //通過x,y,z指定旋轉中心,obj是要旋轉的對象
        //function changePivot(x, y, z, obj) {
        //  let wrapper = new THREE.Object3D();
        //wrapper.position.set(250, 250, 250);
        //wrapper.add(mesh8);
        //mesh8.position.set(x, y, z);
        //return wrapper;
        //}
        //changePivot();


        //創建控件對象  相機對象camera作為參數   控件可以監聽鼠標的變化,改變相機對象的屬性
        var controls = new THREE.OrbitControls(camera);

        // onresize 事件會在窗口被調整大小時發生
        window.onresize = function () {
            // 重置渲染器輸出畫布canvas尺寸
            renderer.setSize(width, height);
            // 重置相機投影的相關參數
            k = window.innerWidth / window.innerHeight;//窗口寬高比
            camera.left = -s * k;
            camera.right = s * k;
            camera.top = s;
            camera.bottom = -s;
            // 渲染器執行render方法的時候會讀取相機對象的投影矩陣屬性projectionMatrix
            // 但是不會每渲染一幀,就通過相機的屬性計算投影矩陣(節約計算資源)
            // 如果相機的一些屬性發生了變化,需要執行updateProjectionMatrix ()方法更新相機的投影矩陣
            camera.updateProjectionMatrix();
        };


        // onresize 事件會在窗口被調整大小時發生
        window.onresize = function () {
            // 重置渲染器輸出畫布canvas尺寸
            renderer.setSize(width, height);
            // 全屏情況下:設置觀察范圍長寬比aspect為窗口寬高比
            camera.aspect = window.innerWidth / window.innerHeight;
            // 渲染器執行render方法的時候會讀取相機對象的投影矩陣屬性projectionMatrix
            // 但是不會每渲染一幀,就通過相機的屬性計算投影矩陣(節約計算資源)
            // 如果相機的一些屬性發生了變化,需要執行updateProjectionMatrix ()方法更新相機的投影矩陣
            camera.updateProjectionMatrix();
        };

        //創建控件對象  相機對象camera作為參數   控件可以監聽鼠標的變化,改變相機對象的屬性
        var control = new THREE.OrbitControls(camera);

        //監聽鼠標事件,觸發渲染函數,更新canvas畫布渲染效果
        control.addEventListener('change', render);
    </script>
</body>
</html>

  相關學習群

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM