1. 程式人生 > >Three.js 開發機房(四)

Three.js 開發機房(四)

這一節我們講講怎麼畫機櫃,其實機櫃如果作的複雜一點、逼真一點可以用3D建模工具,不過一般的專案中也不用做的那麼麻煩,那我們就可以將機櫃抽象以下,首先它是一塊具有長寬高的立方體鐵塊,然後我們從中間在掏掉一個小一號的立方體同時掏出出一個門的位置就好了,程式碼如下

 initCabient() {
    let _self = this;
    // 用打組有個好處是我們不用管group中的Mesh的位置,我們只需要操控Group的位置
    this.initCabientObject = new Group();
    var Cabinet_material = new THREE.MeshPhongMaterial({
        color: 0x42474c,
    });
    // 注意此處不能用之前初始化同來克隆的幾何體,因為用來克隆的集合體的長寬高都為1,我們看到的都是放大的,而本體尺寸其實並沒有改變,所以用幾何體做減法的時候會被減沒了
    var Cabinet = _self.returnLambertObject(60, 200, 60, 0, Cabinet_material, 0, 0, 0);
    var Cabinet_inside = _self.returnLambertObject(54, 196, 56, 0, Cabinet_material, 3, 0, 0);
    this.initCabientObject.add(_self.returnResultBsp(Cabinet, Cabinet_inside, 2, 0)); // 這一步一個掏空的盒子已經出現了

    // 以下三行程式碼僅做演示用
    this.initCabientObject.position.set(0, 100, 0);
    this.initCabientObject.rotation.y = 1 * Math.PI;
    this.scene.add(this.initCabientObject);
}

  程式碼執行結果如下圖(注意要在init方法中呼叫以下):

就這樣一個被掏空的盒子就出現了,盒子出來了還缺啥?眼尖的朋友已經看出來了,缺個門,對,缺門我們就畫個門,門的素材上篇文章畫牆的時候已經引進來了,那我麼直接拿素材用就好了,

var doorgeometry = new THREE.BoxGeometry(55, 190, 2);
var door = new THREE.Mesh(doorgeometry, _self.DoorRenderingList);
door.position.set(30, 0, 0);
door.rotation.y = 0.5 * Math.PI; //-逆時針旋轉,+順時針
door.nature = "Cabinet__door";
door.isClose = 1;
this.initCabientObject.add(door);

  把門初始化完成後然後塞到initCabientObject中即可,效果如下(小了看不太清楚)

這樣一個機櫃就成型了,是不是很簡單呢!當然我們這個 initCabient 方法大家從名字上就能看出他只是初始化而不是畫機櫃,所以在這個函式裡以下三那句話就得刪掉了

this.initCabientObject.position.set(0, 100, 0);
this.initCabientObject.rotation.y = 1 * Math.PI;
this.scene.add(this.initCabientObject);

    這裡一個機櫃(不包含裝置)的組就完成了,雖說Group不能被raycaster鐳射器選中,可是其優越性在這塊就很突出了,我們不需要管不同方向時機櫃的門怎麼開,不同方向不同位置機櫃裡面的裝置的方向和位置是不是也要發生改變,我們只需要控制整個組的位置和角度就好了,就像本來廣場上有很多人,我們需要控制每個人的位置和麵對的方向很麻煩,但是如果我們讓廣場上的人上了一輛汽車(假設汽車很大,能容納下廣場上的所有人),那麼要控制車裡面的乘客的位置和方向就很簡單了,我們不用管裡面的乘客的位置,只需要知道汽車的位置和方向就OK了。

      既然initCabient這個方法不是用來畫機櫃的,那它是用來幹啥的呢?當然是做模型,就像工廠要生產一批機櫃,他不需要每件產品都單獨生產,只需要先生產一個模板,然後其他的就按照這個模板克隆就好了,這個模板一般情況下並不會交給買家,而是當作模板,不管你什麼時候再要,我只需要繼續按照模板克隆就好了,這也是我從上面將我的模板新增到場景中的那幾句程式碼刪掉的原因。

  接下來我們定義一組機櫃的位置的資料

cabient: [
    { x: 130, z: 120, codeID: "XZ100001", angle: 0 },
    { x: 230, z: 120, codeID: "XZ100002", angle: 0.5 },
    { x: 330, z: 120, codeID: "XZ100003", angle: 1 },
    { x: 430, z: 120, codeID: "XZ100004", angle: 1.5 },

]

  然後我們開始封裝通過資料畫機櫃的方法:

/**
   * 往機房裡面新增機櫃的方法
   * @param { 機櫃的資料資訊 } result 
   */
createCabient(result) {
    let _self = this;
    result.map((item) => {
        let cabientMod = _self.initCabientObject.clone();
        cabientMod.position.set(item.x - _self.houseWidth / 2, 100, item.z - _self.houseHeight / 2);
        cabientMod.rotation.y = item.angle * Math.PI;
        // 此處給每個機櫃設定name為 cabient 標識加 _ 再加機櫃ID,後面會用到
        cabientMod.name="cabient_" + item.codeID;
        _self.scene.add(cabientMod);
    })
};

  這樣我們就已經將資料化的機櫃資訊新增到了場景中,看下圖

到這一步機櫃就已經畫好了,下一片文章我將詳細介紹怎麼最簡單的畫裝置以及裝置的一些簡單的動效,好了,這一篇文章到這裡就結束了,如果各位看客覺得這篇文章還行,麻煩點個“推薦”,謝謝!


 

順便說一下,前篇文章釋出一天就有好幾百的瀏覽量,說明鑽研這塊東西的人不少,歡迎各位在評論區指出Three.js系列文章的缺點和不足,之前寫的亂七八糟的文章如果哪有不合適也請不吝賜教,技術文章寧可不寫也不能因為寫的裡面有錯而誤導