BabylonJS系列:方向?qū)Ш胶?1.創(chuàng)建盒子模型

這一節(jié)主要編寫生成導航盒模型的代碼,將以創(chuàng)造自定義模型為中心進行講解。想閱覽相關(guān)官方文檔的小伙伴可以自行前往(https://doc.babylonjs.com/features/featuresDeepDive/mesh/creation/custom/custom
說到自定義生成模型,我們很難離開VertexData,VertexData對Mesh的各項基礎(chǔ)buffer的設(shè)置和獲取提供了一層封裝,我們可以使用VertexData去讀取/修改/設(shè)置Mesh的基本Buffer。它常用的幾個字段如下

class VertexData{
  position:number[];     //頂點數(shù)組 頂點數(shù)*3
  colors:number[];       //顏色數(shù)組 頂點數(shù)*3或4
  indices:number[];      //索引數(shù)組 面數(shù)*3
  normals:number[];      //法線數(shù)組 頂點數(shù)*3
  uvs:number[]           //uv0數(shù)組 頂點數(shù)*2
  ......
  uvs6:number[]          //uv6數(shù)組 頂點數(shù)*2
}

我們在實例化Mesh之前,我們需要準備好需要用到的基礎(chǔ)數(shù)據(jù)的數(shù)組,normals法線一般使用VertexData.ComputeNormals直接計算得出。
在這個案例中,我們需要準備positions, indices和uvs,然后通過計算獲取normals。下為創(chuàng)建Mesh過程的步驟代碼,對準備頂點數(shù)據(jù)的過程有興趣的小伙伴可以前往PG。

//自定義數(shù)據(jù)接口
interface ICustomVertexData {
    positions: number[],
    indices: number[],
    uvs: number[]
}
class DirectBoxCreator {
    //創(chuàng)建盒子
    static create(scene: BABYLON.Scene, size: number, edgePercent: number) {
        const front = B.Vector3.Forward();
        const back = B.Vector3.Backward();
        const right = B.Vector3.Right();
        const left = B.Vector3.Left();
        const up = B.Vector3.Up();
        const down = B.Vector3.Down();
        const data: ICustomVertexData = {
            positions: [],
            indices: [],
            uvs: [],
        }
        //創(chuàng)建6個面
        //創(chuàng)建正面
        this.createFace(size,edgePercent,back, up, right, new B.Vector2(0, 0), data);
        ......
        //創(chuàng)建8個角
        // 創(chuàng)建左上前角
        this.createEdge(size,edgePercent,new B.Vector3(-size, size, -size), right, down, front, data);
        ......
        //準備VertexData
        const vertexData = new B.VertexData();
        vertexData.positions = data.positions;
        vertexData.indices = data.indices;
        vertexData.uvs = data.uvs;
        const normals: number[] = [];
        B.VertexData.ComputeNormals(data.positions, data.indices, normals);
        vertexData.normals = normals;

        //創(chuàng)建Mesh
        const mesh = new B.Mesh("DirectBox", scene);
        //創(chuàng)建材質(zhì)
        const material = new B.StandardMaterial("DirectBoxMat", scene);
        mesh.material = material;
        material.disableLighting = true;
        material.emissiveTexture = new BABYLON.Texture("https://moriyer.github.io/BabylonTexture/JianShu/Texture/DirectBox.jpg", scene, undefined, false);
        //將vertexData數(shù)據(jù)應(yīng)用進Mesh
        vertexData.applyToMesh(mesh);

        return {
            mesh,
            material,
        };
    }
    private static createFace(size: number, edgePercent: number, origin: BABYLON.Vector3, up: BABYLON.Vector3, right: BABYLON.Vector3, uvOffset: BABYLON.Vector2, data: ICustomVertexData) {
        //計算過程,uvOffset參數(shù)是因為貼圖問題手動配置偏置
    }
    private static createEdge(size: number, edgePercent: number, origin: BABYLON.Vector3, dir1: BABYLON.Vector3, dir2: BABYLON.Vector3, dir3: BABYLON.Vector3, data: ICustomVertexData) {
        //計算過程
    }
}
(https://playground.babylonjs.com/?#ENABP9#6)

此時的盒子已經(jīng)完成,美中不足的是棱角不夠明顯,我們可以給Mesh加上Edge讓棱角突出

        mesh.enableEdgesRendering(0.99);  //激活Edge
        mesh.edgesWidth = 6;              //設(shè)置Edge寬度
        mesh.edgesColor.set(0, 0, 0, 1);  //設(shè)置黑色
        (https://playground.babylonjs.com/?#ENABP9#7)
image.png

添加Edge后,棱角有明顯的線條,但是會發(fā)現(xiàn)棱角粗細不一,旋轉(zhuǎn)的時候棱角閃爍,這是一個典型的z-fight問題,深度距離接近導致有些角度Edge被盒子遮住,從而產(chǎn)生閃爍。對于這種問題,我們可以讓盒子沿著法線的z軸縮放一點點。

mesh.material.zOffset = 1;


PS:最終的PG:https://playground.babylonjs.com/?#ENABP9#8

下一節(jié):BabylonJS系列:方向?qū)Ш胶?2.創(chuàng)建導航盒場景

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容