這一節(jié)主要編寫生成導(dǎo)航盒模型的代碼,將以創(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問題番捂,深度距離接近導(dǎo)致有些角度Edge被盒子遮住个唧,從而產(chǎn)生閃爍。對于這種問題设预,我們可以讓盒子沿著法線的z軸縮放一點點徙歼。
mesh.material.zOffset = 1;
PS:最終的PG:https://playground.babylonjs.com/?#ENABP9#8