three.js 02-04 之網格物件函式及屬性
阿新 • • 發佈:2019-02-08
上一篇中,我們對自定義幾何體的相關知識做了一個簡單介紹,並講解了如何克隆(複製)一個幾何體。本篇我們要介紹的是關於 Mesh 網格物件常用的一些相關函式和屬性。照例,我們先上一個完整的示例,程式碼如下:
在這個示例中,你會看到一些下拉選單,通過這個選單你可以修改如 scale 比例、position 位置、rotation 旋轉、translation 轉移及 visible 可見等屬性,而且立即就可以看到修改結果。現在讓我們來逐一瞭解這些屬性或者相關函式:<!DOCTYPE html> <html> <head> <title>示例 02.04 - 網格物件屬性</title> <script src="../build/three.js"></script> <script src="../build/js/ParametricGeometries.js"></script> <script src="../build/js/QuickHull.js"></script> <script src="../build/js/geometries/ConvexGeometry.js"></script> <script src="../build/js/controls/OrbitControls.js"></script> <script src="../build/js/libs/stats.min.js"></script> <script src="../build/js/libs/dat.gui.min.js"></script> <script src="../jquery/jquery-3.2.1.min.js"></script> <style> body { /* 設定 margin 為 0,並且 overflow 為 hidden,來完成頁面樣式 */ margin: 0; overflow: hidden; } /* 統計物件樣式 */ #Stats-output { position: absolute; left: 0px; top: 0px; } </style> </head> <body> <!-- 用於 WebGL 輸出的 Div --> <div id="WebGL-output"></div> <!-- 用於統計 FPS 輸出的 Div --> <div id="Stats-output"></div> <!-- 執行 Three.js 示例的 Javascript 程式碼 --> <script type="text/javascript"> var scene; var camera; var render; var controls; var stats; var guiParams; var gui; var plane; var mesh; // 當所有元素載入完畢後,就執行我們 Three.js 相關的東西 $(function() { stats = initStats(); scene = new THREE.Scene(); camera = new THREE.PerspectiveCamera(45, window.innerWidth / window.innerHeight, 0.1, 1000); // 2147483647 camera.position.set(-20, 25, 20); render = new THREE.WebGLRenderer( {antialias: true} ); // antialias 抗鋸齒 render.setSize(window.innerWidth, window.innerHeight); render.setClearColor(0xEEEEEE); render.shadowMap.enabled = true; // 允許陰影投射 $('#WebGL-output')[0].appendChild(render.domElement); window.addEventListener('resize', onWindowResize, false); var target = new THREE.Vector3(5, 0, 0); controls = new THREE.OrbitControls(camera, render.domElement); controls.target = target; // 解決 camera.lookAt(x, y, z) 失效問題 camera.lookAt(target); scene.add(new THREE.AxisHelper(20));// 加入座標軸 // 加入一個平面 var planeGeometry = new THREE.PlaneGeometry(60, 40, 1, 1); var planeMaterial = new THREE.MeshLambertMaterial( {color: 0xFFFFFF} ); plane = new THREE.Mesh(planeGeometry, planeMaterial); plane.rotation.x = -0.5 * Math.PI; // 沿著 X軸旋轉-90° plane.position.x = 0; plane.position.y = 0; plane.position.z = 0; plane.receiveShadow = true; // 幾何平面接收陰影 scene.add(plane); // 加入一個環境光源 var ambientLight = new THREE.AmbientLight(0x090909); scene.add(ambientLight); // 加入一個聚光燈光源 // 注:基礎材質 MeshBasicMaterial 不會對光源產生反應,因此要改用 MeshLambertMaterial 或 MeshPhongMaterial 材質才有效果 var spotLight = new THREE.SpotLight( 0xFFFFFF); spotLight.position.set(-40, 40, 50); spotLight.castShadow = true; // 光源產生陰影 spotLight.shadow.mapSize.width = 1024; // 必須是 2的冪,預設值為 512 spotLight.shadow.mapSize.height = 1024; // 必須是 2的冪,預設值為 512 scene.add(spotLight); // 定義 gui 控制引數 guiParams = new function() { function addControlPoint(x, y, z) { var controlPoint = new function() { this.x = x; this.y = y; this.z = z; }; return controlPoint; } this.scale = addControlPoint(1, 1, 1); this.position = addControlPoint(0, 4, 0); this.rotation = addControlPoint(1, 1, 1); this.translation = addControlPoint(0, 0, 0); this.visible = true; } // 定義 gui 並繫結引數 gui = new dat.GUI(); var folder = gui.addFolder('scale'); folder.add(guiParams.scale, 'x', 0, 5); folder.add(guiParams.scale, 'y', 0, 5); folder.add(guiParams.scale, 'z', 0, 5); folder = gui.addFolder('position'); folder.add(guiParams.position, 'x', -10, 10); folder.add(guiParams.position, 'y', -4, 20); folder.add(guiParams.position, 'z', -10, 10); folder = gui.addFolder('rotation'); folder.add(guiParams.rotation, 'x', -4, 4); folder.add(guiParams.rotation, 'y', -4, 4); folder.add(guiParams.rotation, 'z', -4, 4); folder = gui.addFolder('translate'); folder.add(guiParams.translation, 'x', -10, 10); folder.add(guiParams.translation, 'y', -10, 10); folder.add(guiParams.translation, 'z', -10, 10); gui.add(guiParams, 'visible'); var material = new THREE.MeshLambertMaterial({color: 0x44ff44}); var geom = new THREE.BoxGeometry(5, 8, 3); mesh = new THREE.Mesh(geom, material); mesh.position.y = 4; mesh.castShadow = true; scene.add(mesh); renderScene(); }); /** 初始化 stats 統計物件 */ function initStats() { stats = new Stats(); stats.setMode(0); // 0 為監測 FPS;1 為監測渲染時間 $('#Stats-output').append(stats.domElement); return stats; } /** 渲染場景 */ function renderScene() { stats.update(); updateMesh(); // 更新物體 requestAnimationFrame(renderScene); render.render(scene, camera); } /** 當瀏覽器視窗大小變化時觸發 */ function onWindowResize() { camera.aspect = window.innerWidth / window.innerHeight; camera.updateProjectionMatrix(); render.setSize(window.innerWidth, window.innerHeight); } /** 更新物體 */ function updateMesh() { mesh.visible = guiParams.visible; mesh.scale.set(guiParams.scale.x, guiParams.scale.y, guiParams.scale.z); mesh.position.set(guiParams.position.x, guiParams.position.y, guiParams.position.z); mesh.rotation.set(guiParams.rotation.x, guiParams.rotation.y, guiParams.rotation.z); mesh.translateX(guiParams.translation.x); mesh.translateY(guiParams.translation.y); mesh.translateZ(guiParams.translation.z); } </script> </body> </html>
- position - 通過這個屬性我們可以改變物件在場景中的 x, y, z 座標上的位置。需要注意的是,一個物件的位置是相對於其父物件來講的,而父物件通常是你向其新增物件的那個場景。一般有以下幾種方式來改變物件的位置:第一種是 mesh.position.x = 5, mesh.position.y = 6, mesh.position.z = 7;第二種是示例中用到的那種方式;第三種是 mesh.position.setX(1), mesh.position.setY(1), mesh.position.setZ(1);
- rotation - 通過這個屬性我們可以改變物件繞軸 x, y, z 旋轉的弧度。旋轉一週的弧度是 2 * Math.PI。方向的確定是用右手來測定的,方法是用右手握住要繞轉的軸,拇指方向與軸的箭頭方向保持一致,那麼四指所指的方向就是正方向;
- scale - 通過這個屬性我們可以改變物件在 x, y, z 軸方向的比例。即沿指定軸縮放物件。當設的值小於 1 時,就是縮小;反之,就是放大;
- translate - 通過這個屬性我們一樣可以達到類似 position 的效果。但是 translate 函式不是定義物件想要放在哪裡的絕對位置,而是定義相對於當前位置物件移動的量。舉個例子,假定場景中的一個立方體的位置是 (1, 2, 3),接下來我們把物件沿著 x 軸平移 4 個單位,即 translateX(4),那麼它現在的位置就變為了(5, 2, 3)。如果想要恢復它原來的位置,則可以呼叫 translateX(-4) 即可完成。當然直接呼叫 position.setX(1) 亦可達到相同效果;
- visible - 通過它來設定物件在場景中的可見性。true 為可見;false 為不可見;