BabylonJS系列:方向导航盒 1.创建盒子模型

这一节主要编写生成导航盒模型的代码,将以创造自定义模型为中心进行讲解。想阅览相关官方文档的小伙伴可以自行前往(https://doc.babylonjs.com/features/featuresDeepDive/mesh/creation/custom/custom
说到自定义生成模型,我们很难离开VertexData,VertexData对Mesh的各项基础buffer的设置和获取提供了一层封装,我们可以使用VertexData去读取/修改/设置Mesh的基本Buffer。它常用的几个字段如下

class VertexData{
  position:number[];     //顶点数组 顶点数*3
  colors:number[];       //颜色数组 顶点数*3或4
  indices:number[];      //索引数组 面数*3
  normals:number[];      //法线数组 顶点数*3
  uvs:number[]           //uv0数组 顶点数*2
  ......
  uvs6:number[]          //uv6数组 顶点数*2
}

我们在实例化Mesh之前,我们需要准备好需要用到的基础数据的数组,normals法线一般使用VertexData.ComputeNormals直接计算得出。
在这个案例中,我们需要准备positions, indices和uvs,然后通过计算获取normals。下为创建Mesh过程的步骤代码,对准备顶点数据的过程有兴趣的小伙伴可以前往PG。

//自定义数据接口
interface ICustomVertexData {
    positions: number[],
    indices: number[],
    uvs: number[]
}
class DirectBoxCreator {
    //创建盒子
    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: [],
        }
        //创建6个面
        //创建正面
        this.createFace(size,edgePercent,back, up, right, new B.Vector2(0, 0), data);
        ......
        //创建8个角
        // 创建左上前角
        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;

        //创建Mesh
        const mesh = new B.Mesh("DirectBox", scene);
        //创建材质
        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数据应用进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参数是因为贴图问题手动配置偏置
    }
    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)

此时的盒子已经完成,美中不足的是棱角不够明显,我们可以给Mesh加上Edge让棱角突出

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

添加Edge后,棱角有明显的线条,但是会发现棱角粗细不一,旋转的时候棱角闪烁,这是一个典型的z-fight问题,深度距离接近导致有些角度Edge被盒子遮住,从而产生闪烁。对于这种问题,我们可以让盒子沿着法线的z轴缩放一点点。

mesh.material.zOffset = 1;


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

下一节:BabylonJS系列:方向导航盒 2.创建导航盒场景

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容