<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          關(guān)于從入門three.js到做出3d地球這件事(第二篇: 開發(fā)必備的輔助技能)

          共 11714字,需瀏覽 24分鐘

           ·

          2021-04-10 13:06

          來源:lulu_up

          https://segmentfault.com/a/1190000039683111

          本篇介紹

          開發(fā)3d效果的時候, 不能每次都通過刷新頁面來更新圖像, 我們工程師當(dāng)然會發(fā)明出相應(yīng)的工具輔助開發(fā)工作, 這一篇我們一起學(xué)習(xí)三個好用的工具, 讓我們的開發(fā)更暢快。

          上篇我們講解了three.js的基本配置代碼, 想看的同學(xué)可以訪問這個鏈接: 關(guān)于從入門three.js到做出3d地球這件事(第一篇: 通俗易懂的入門)

          一. 相機(jī)的配置

          • 這里介紹的是透視相機(jī)

          介紹工具之前我們先把相機(jī)的關(guān)鍵概念系統(tǒng)的學(xué)一遍, 因為以后我們要利用相機(jī)做很多有趣的事。???? 這里以上一篇繪制的最基本的坐標(biāo)系為例進(jìn)行說明, 如下圖:

          第一: position 相機(jī)位置

          位置屬性很重要很常用, 不同的位置呈現(xiàn)出不同的景色, 我們可以把相機(jī)理解為我們在3d世界中的眼睛, 而調(diào)整相機(jī)的位置就相當(dāng)于我們走到不同的角度去看這個3d世界。???? 看過上一篇你會知道我們的相機(jī)實例叫camera, 我們對他的position屬性進(jìn)行設(shè)置就可以調(diào)整位置。

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

          上面就是分別調(diào)節(jié)了相機(jī)的x, y, z軸的距離, 我們看到的景象變成了下面的樣子。

          • 第二種設(shè)置方式

          position身上有set方法可以設(shè)置, 三個參數(shù)對應(yīng)的是x, y, z。

          camera.position.set(2210)

          效果與上面的一樣。

          • 第三種設(shè)置方式

          position可以直接設(shè)置x, y, z屬性, 本身又有set方法, 那么position屬性本身到底是個什么那? 讓我們打印出來看看。isVector3: true也就是說它是一個Vector實例, 那么Vector是什么? 我們以后會經(jīng)常和這個單詞打交道, 讓我們一起記住它。

          • 先不細(xì)聊向量

          因為向量是個很重要的概念, 我們后面會單獨大篇幅的詳談, 這里咱們單純的理解為new THREE.Vector3(2, 2, 10)是生成了一個, 參數(shù)就是這個點的xyz坐標(biāo), 而我們相機(jī)的position屬性就是這樣一個對象。

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

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

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

          • 別被唬住

          上面展示了大部分常用的設(shè)置position的方法, 我在初學(xué)three.js的時候被網(wǎng)上各種寫法弄暈了所以這里特意列出大部分寫法, 希望當(dāng)你再看其它資料的時候就不會被亂七八糟的寫法唬住了。

          第二: lookAt 相機(jī)看向哪里

          這個概念簡直太重要了, 如其字面意思就是看向哪里, 上面相機(jī)位置已經(jīng)調(diào)整完畢, 那么我們要調(diào)整相機(jī)拍攝哪里了。

          默認(rèn)是(0,0,0)的位置如下圖:

          當(dāng)我們看向坐標(biāo)系的 (3, 3, 0)位置也就是右上角:

          從它的效果我們可以發(fā)現(xiàn), 這個屬性非常適合在3d游戲中調(diào)整人物的方向時改變圖像, 如果你要做第一人稱游戲一個人在城市里奔跑的效果, 那無非就是不斷的改變相機(jī)的positionlookAt就能做到了。

          • 設(shè)置方式

          這里可以直接設(shè)置: camera.lookAt(3, 3, 0); 還可以利用向量來設(shè)置: camera.lookAt(new THREE.Vector3(3, 3, 0));

          第三: up 誰為相機(jī)上方

          先來一張默認(rèn)的情況, 不難看出綠的是y, 紅的是x, z正對著我們所以暫時看不到:

          我們設(shè)置一下camera.up.set(1, 0, 0);

          上面x的值成為了最大, 所以他變成了上方的坐標(biāo)軸, 當(dāng)然如我們設(shè)一個亂亂的值camera.up.set(1, 0.5, 0); 那么效果如下:

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

          可以利用這個屬性模擬第一人稱游戲里任務(wù)摔倒了看這個世界....

          坑點

          我當(dāng)前版本的three.js想要up屬性生效需要在設(shè)置完up屬性之后再主動指定一下camera.lookAt(0, 0, 0);否則up屬性不生效;

          二. GUI的使用

          上面講了這么多, 我們現(xiàn)在想讓場景動起來, 所以需要不斷的渲染出3d圖像, 我們利用requestAnimationFrame反復(fù)調(diào)用渲染函數(shù)就能實現(xiàn)動畫效果了。

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

          -全名dat.gui.js他的功能是為屬性生成一個可調(diào)節(jié)值的面板, 方便我們不斷修改數(shù)值而不用刷新頁面如下圖:鼠標(biāo)拖動調(diào)節(jié)

          -引入GUI<script src="https://cdn.bootcdn.net/ajax/libs/dat-gui/0.7.7/dat.gui.min.js"></script>引入之后我們?nèi)侄嗔艘粋€dat屬性。

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

          參數(shù)解答

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

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

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

          知道上面這些就可以應(yīng)付很多的場景了, 一個工具而已不用深究啦。

          全部代碼
          <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(35window.innerWidth / window.innerHeight, 11000);
                  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 = {
                      x0
                  }
                  function createUI() {
                      var gui = new dat.GUI();
                      gui.add(pames, "x"05).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官網(wǎng)地址。

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

          const tween = new TWEEN.Tween(camera.position).to({
              x10,
              y10
          }, 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), 這個動無限循環(huán)。
          4. .start();, 開始執(zhí)行動畫。
          5. .stop();, 停止動畫。
          6. TWEEN.update();, 每次調(diào)用渲染函數(shù)都要調(diào)用一下動畫的更新函數(shù)。

          效果如下(思否暫時無法傳gif圖片, 但我已經(jīng)向高老板反應(yīng)了):

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

          這個庫大概的原理就是每次調(diào)用update方法的時候判斷一下該動畫已經(jīng)執(zhí)行了多久時間, 然后算出當(dāng)前時間目標(biāo)對象的值應(yīng)該變?yōu)槎嗌? 當(dāng)然它還會對性能有所優(yōu)化。

          全部代碼如下:
          <html>
          <style>
              * {
                  padding0;
                  margin0;
              }
          </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(35window.innerWidth / window.innerHeight, 11000);
                  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({
                      x10,
                      y10
                  }, 2000).repeat(Infinity).start()
                  const animate = function () {
                      TWEEN.update()
                      requestAnimationFrame(animate);
                      renderer.render(scene, camera);
                  }
                  animate();
              </script>

          </body>

          </html>

          四. 軌道控制器的使用

          這個就厲害了, 讓我們可以使用鼠標(biāo)轉(zhuǎn)動我們的相機(jī), 仿若進(jìn)入到3d世界一般。

          隨著我們按住鼠標(biāo)并且移動, 視角就隨之變化仿佛身臨其境一般。

          // 將軌道控制器的代碼放在對應(yīng)的文件夾里面, 如果你沒找到就用下面我分享的文件。
          <script src="./utils/OrbitControls.js"></script>

          引入成功頁面THREE身上會出現(xiàn)OrbitControls方法, 我們需要傳入相機(jī)與渲染的容器。

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

          cdn上我沒查到, 想要獲取代碼的同學(xué)可以復(fù)制我的筆記內(nèi)容到項目中 three.js軌道控制器點擊預(yù)覽

          直接在頁面引入與通過npm包的方式引入有區(qū)別, 到了講在vue里的使用的時候我們再詳細(xì)說。
          全部代碼如下: (要有./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(35window.innerWidth / window.innerHeight, 11000);
                  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.

          下一篇將會介紹 光源, 與 陰影的玩法了, 希望與你一起進(jìn)步。

          最后

          歡迎關(guān)注【前端瓶子君】??ヽ(°▽°)ノ?
          回復(fù)「算法」,加入前端算法源碼編程群,每日一刷(工作日),每題瓶子君都會很認(rèn)真的解答喲!
          回復(fù)「交流」,吹吹水、聊聊技術(shù)、吐吐槽!
          回復(fù)「閱讀」,每日刷刷高質(zhì)量好文!
          如果這篇文章對你有幫助,在看」是最大的支持
          》》面試官也在看的算法資料《《
          “在看和轉(zhuǎn)發(fā)”就是最大的支持
          瀏覽 38
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  精品999久久久一级毛片 | se综合| 欧美mv日韩mv国产网站app | 青青青青青欧美在线观视频观看 | 欧美日日干 |