關於從入門three.js到作出3d地球這件事(第二篇: 開發必備的輔助技能)

關於從入門three.js到作出3d地球這件事(第二篇: 開發必備的輔助技能)

本篇介紹

     開發3d效果的時候, 不能每次都經過刷新頁面來更新圖像, 咱們工程師固然會發明出相應的工具輔助開發工做, 這一篇咱們一塊兒學習三個好用的工具, 讓咱們的開發更暢快。html

     上篇咱們講解了three.js的基本配置代碼, 想看的同窗能夠訪問這個連接: 關於從入門three.js到作出3d地球這件事(第一篇: 通俗易懂的入門)vue

一. 相機的配置

  • 這裏介紹的是透視相機

     介紹工具以前咱們先把相機的關鍵概念系統的學一遍, 由於之後咱們要利用相機作不少有趣的事。
     這裏以上一篇繪製的最基本的座標系爲例進行說明, 以下圖:
image.pngajax

第一: position 相機位置

     位置屬性很重要很經常使用, 不一樣的位置呈現出不一樣的景色, 咱們能夠把相機理解爲咱們在3d世界中的眼睛, 而調整相機的位置就至關於咱們走到不一樣的角度去看這個3d世界。
     看過上一篇你會知道咱們的相機實例叫camera, 咱們對他的position屬性進行設置就能夠調整位置。npm

  • 第一種設置方式
camera.position.x = 2;
    camera.position.y = 2;
    camera.position.z = 10;

上面就是分別調節了相機的x, y, z軸的距離, 咱們看到的景象變成了下面的樣子。
image.pngsegmentfault

  • 第二種設置方式

     position身上有set方法能夠設置, 三個參數對應的是x, y, z。app

camera.position.set(2, 2, 10)

     效果與上面的同樣。dom

  • 第三種設置方式

     position能夠直接設置x, y, z屬性, 自己又有set方法, 那麼position屬性自己究竟是個什麼那? 讓咱們打印出來看看。
image.png
isVector3: true也就是說它是一個Vector實例, 那麼Vector是什麼?
咱們之後會常常和這個單詞打交道, 讓咱們一塊兒記住它。
image.png函數

  • 先不細聊向量

由於向量是個很重要的概念, 咱們後面會單獨大篇幅的詳談, 這裏我們單純的理解爲new THREE.Vector3(2, 2, 10)是生成了一個, 參數就是這個點的xyz座標, 而咱們相機的position屬性就是這樣一個對象。工具

  • 注意: 直接賦值是無效的

camera.position = new THREE.Vector3(2, 2, 10) 無效性能

須要利用add方法來實現
camera.position.add(new THREE.Vector3(2, 2, 10)) 有效

  • 別被唬住

上面展現了大部分經常使用的設置position的方法, 我在初學three.js的時候被網上各類寫法弄暈了因此這裏特地列出大部分寫法, 但願當你再看其它資料的時候就不會被亂七八糟的寫法唬住了。

第二: lookAt 相機看向哪裏

     這個概念簡直過重要了, 如其字面意思就是看向哪裏, 上面相機位置已經調整完畢, 那麼咱們要調整相機拍攝哪裏了。

默認是(0,0,0)的位置以下圖:
image.png

當咱們看向座標系的 (3, 3, 0)位置也就是右上角:
image.png

     從它的效果咱們能夠發現, 這個屬性很是適合在3d遊戲中調整人物的方向時改變圖像, 若是你要作第一人稱遊戲一我的在城市裏奔跑的效果, 那無非就是不斷的改變相機的positionlookAt就能作到了。

  • 設置方式

這裏能夠直接設置: camera.lookAt(3, 3, 0);
還能夠利用向量來設置: camera.lookAt(new THREE.Vector3(3, 3, 0));

第三: up 誰爲相機上方

先來一張默認的狀況, 不難看出綠的是y, 紅的是x, z正對着咱們因此暫時看不到:
image.png

咱們設置一下camera.up.set(1, 0, 0);
image.png

上面x的值成爲了最大, 因此他變成了上方的座標軸, 固然如咱們設一個亂亂的值camera.up.set(1, 0.5, 0); 那麼效果以下:
image.png

這個屬性的設置方式就是set方法或者camera.up = new THREE.Vector3(1, 0.5, 0);

能夠利用這個屬性模擬第一人稱遊戲裏任務摔倒了看這個世界....

坑點

我當前版本的three.js想要up屬性生效須要在設置完up屬性以後再主動指定一下camera.lookAt(0, 0, 0);不然up屬性不生效;

二. GUI的使用

     上面講了這麼多, 咱們如今想讓場景動起來, 因此須要不斷的渲染出3d圖像, 咱們利用requestAnimationFrame反覆調用渲染函數就能實現動畫效果了。

const animate = function () {
        requestAnimationFrame(animate);
        renderer.render(scene, camera);
    };
animate();

-全名dat.gui.js
他的功能是爲屬性生成一個可調節值的面板, 方便咱們不斷修改數值而不用刷新頁面以下圖:
image.png
鼠標拖動調節
image.png

image
-引入GUI
<script src="https://cdn.bootcdn.net/ajax/libs/dat-gui/0.7.7/dat.gui.min.js"></script>
引入以後咱們全局多了一個dat屬性。

const gui = new dat.GUI();
// 1: 定義一個咱們要改變的對象
const pames = {
  x: 0
}
// 2: 把這個值放入控制器
gui.add(pames, "x", 0, 5).name("x軸的距離")

參數解答

  1. 傳入要改變的對象。
  2. 要改變這個對象身上的哪一個屬性。
  3. 最小值
  4. 最大值
  5. .name('顯示在調節欄的名稱')

在每次渲染的時候更新一下相機的x軸位置。

const animate = function () {
    camera.position.x = pames.x
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
}
animate();

知道上面這些就能夠應付不少的場景了, 一個工具而已不用深究啦。

所有代碼
<html>
    <script src="https://cdn.bootcdn.net/ajax/libs/three.js/r122/three.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/dat-gui/0.7.7/dat.gui.min.js"></script>
    <script>
        const scene = new THREE.Scene();
        const camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 1, 1000);
        camera.position.z = 20;
        const renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.setClearColor(0x00FFFF, .5);
        document.body.appendChild(renderer.domElement);
        const axisHelper = new THREE.AxisHelper(2)
        scene.add(axisHelper)
        const pames = {
            x: 0
        }
        function createUI() {
            var gui = new dat.GUI();
            gui.add(pames, "x", 0, 5).name("x軸的距離")
        }
        const animate = function () {
            camera.position.x = pames.x
            requestAnimationFrame(animate);
            renderer.render(scene, camera);
        }
        createUI()
        animate();
    </script>
</body>
</html>

三. tween的使用

     tween.js是用來作流暢動畫的庫, 比咱們本身寫動畫方便多了tween官網地址

下面編寫了一個相機平滑的向右上角移動的代碼。

const tween = new TWEEN.Tween(camera.position).to({
    x: 10,
    y: 10
}, 2000).repeat(Infinity).start();

 // tween.stop() // 能夠中止動畫
 
const animate = function () {
    TWEEN.update();
    requestAnimationFrame(animate);
    renderer.render(scene, camera);
}
animate();
  1. new TWEEN.Tween("這裏傳入要改變的對象")
  2. .to( x: 10 y: 10}, 2000), 在2000毫秒時將x與y屬性變成10。
  3. .repeat(Infinity), 這個動無限循環。
  4. .start();, 開始執行動畫。
  5. .stop();, 中止動畫。
  6. TWEEN.update();, 每次調用渲染函數都要調用一下動畫的更新函數。

效果以下(思否暫時沒法傳gif圖片, 但我已經向高老闆反應了):
image.png
image.png

下面是動圖, 顯示可能有問題。
image

這個庫大概的原理就是每次調用update方法的時候判斷一下該動畫已經執行了多久時間, 而後算出當前時間目標對象的值應該變爲多少, 固然它還會對性能有所優化。

所有代碼以下:
<html>
<style>
    * {
        padding: 0;
        margin: 0;
    }
</style>

<body>
    <script src="https://cdn.bootcdn.net/ajax/libs/three.js/r122/three.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/tween.js/18.6.4/tween.umd.js"></script>
    <script>
        const scene = new THREE.Scene();
        const camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 1, 1000);
        camera.position.z = 20;
        const renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.setClearColor(0x00FFFF, .5);
        document.body.appendChild(renderer.domElement);
        const axisHelper = new THREE.AxisHelper(2)
        scene.add(axisHelper)

        const tween = new TWEEN.Tween(camera.position).to({
            x: 10,
            y: 10
        }, 2000).repeat(Infinity).start()
        const animate = function () {
            TWEEN.update()
            requestAnimationFrame(animate);
            renderer.render(scene, camera);
        }
        animate();
    </script>
</body>

</html>

四. 軌道控制器的使用

     這個就厲害了, 讓咱們可使用鼠標轉動咱們的相機, 仿若進入到3d世界通常。

image

隨着咱們按住鼠標而且移動, 視角就隨之變化彷彿身臨其境通常。

// 將軌道控制器的代碼放在對應的文件夾裏面, 若是你沒找到就用下面我分享的文件。
<script src="./utils/OrbitControls.js"></script>

引入成功頁面THREE身上會出現OrbitControls方法, 咱們須要傳入相機與渲染的容器。

const orbitControls = new THREE.OrbitControls(camera, renderer.domElement);
  orbitControls.target = new THREE.Vector3(0, 0, 0);//控制焦點

     cdn上我沒查到, 想要獲取代碼的同窗能夠複製個人筆記內容到項目中 three.js軌道控制器

直接在頁面引入與經過npm包的方式引入有區別, 到了講在vue裏的使用的時候咱們再詳細說。
所有代碼以下: (要有./utils/OrbitControls.js的代碼, 沒有的話來我筆記下載)
<html>

<body>
    <script src="https://cdn.bootcdn.net/ajax/libs/three.js/r122/three.min.js"></script>
    <script src="./utils/OrbitControls.js"></script>
    <script>
        const scene = new THREE.Scene();
        const camera = new THREE.PerspectiveCamera(35, window.innerWidth / window.innerHeight, 1, 1000);
        camera.position.z = 10;
        const renderer = new THREE.WebGLRenderer();
        renderer.setSize(window.innerWidth, window.innerHeight);
        renderer.setClearColor(0x00FFFF, .5)
        // 軌道控制器
        orbitControls = new THREE.OrbitControls(camera, renderer.domElement);
        // orbitControls.target = new THREE.Vector3(0, 0, 0);
        // 軌道控制器
        document.body.appendChild(renderer.domElement);
        const axisHelper = new THREE.AxisHelper(2)
        scene.add(axisHelper)
        var animate = function () {
            requestAnimationFrame(animate);
            renderer.render(scene, camera);
        };
        animate();
    </script>
</body>

</html>

end.

下一篇將會介紹 光源, 與 陰影的玩法了, 但願與你一塊兒進步。

相關文章
相關標籤/搜索