天天看点

Babylon.js 第21章 材质映射到网格+贴花

目录

 一、 表面网格

二、正面与背面的网格

三、对不同网格使用多材料

四、网格贴花

 贴花示例:

 一、 表面网格

let col=6
    let row=4
    let faceUV=new Array(6)
    
    for(let i=0;i<6;i++){
        faceUV[i]=new BABYLON.Vector4(i/col,0,(i+1)/col,1/4)
    }
    /*
    *面上的图像反转
    faceUV[0]=new BABYLON.Vector4(0,0,1/2,1/4)
    let temp=faceUV[0].x
    faceUV[0].x=faceUV[0].z
    faceUV[0].z=temp
    let temp1=faceUV[0].y
    faceUV[0].y=faceUV[0].w
    faceUV[0].w=temp1
    */

    let faceColor=new Array(6)
    //应用颜色
    faceColor[0]=new BABYLON.Color4(1,1,0,0)
    faceColor[4]=new BABYLON.Color4(0,0,1,0)
    let box=BABYLON.MeshBuilder.CreateBox(
        'box',
        {width:10,height:5,depth:5,faceUV:faceUV,
        wrap:true,topBaseAt:0,faceColors:faceColor},
        scene
    )
    box.material=sphereMaterial
    sphere.material=sphereMaterial
           

必须使用MeshBuilder才能自定义面上的网格图像。当然faceUV的Vector4有四个参数(x,y,z,w),其实际意思很简单,就是图像的比例,x,y,左下角开始的一个坐标,z,w,右上角的一个坐标,只是其取值是图像的比例,介于0到1之间。(0,0,0.5,1),意识就是截取图像左半部分的图像。依此类推。

option对象参数:

  • wrap - 布尔值(默认 = false),当为 true 时,所有垂直边 (0, 1, 2, 3) 将在正确的垂直方向上应用图像纹理,两个水平边 (4, 5) 将应用图像纹理,以便当框围绕 x 轴旋转以使这些边垂直时,应用的图像纹理将以其原始方向应用;
  • topBaseAt - 整数,0, 1, 2, 3,(默认 = 1),框顶部图像的底部(底部)紧挨着给定数字的一侧;
  • bottomBaseAt- 整数,0, 1, 2, 3,(默认 = 0),框底部图像的底部(底)紧挨着给定数字的一侧。

faceColor也是对应面上应用颜色。

圆柱体的面:圆柱体具有三个表面,顶部、底部和连接它们的管子。对于面选项,面 0 是底部,面 1 是管,面 2 是顶部。

挤压多边形具有顶部、底部和挤压边三个表面,面 0 是顶部,面 1 是挤压边,面 2 是底部。

可以将纹理图集与所有多面体一起使用,但是如果不仔细考虑纹理图集的性质,结果可能看起来有点随机。 

二、正面与背面的网格

frontUVs 和 backUVs 都具有 Vector4(u0, v0, u1, v1) 的形式,其中 0<= u0, v0, u1, v1 <= 1 和 (u0, v0) 是左下角坐标, (u1, v1) 是顶部坐标图像剪切矩形的右坐标。

要拆分上面的图像,您可以形成两个变量

let f=new BABYLON.Vector4(0,0,0.5,1)
    let b=new BABYLON.Vector4(0.5,0,1,1)
    let plane=BABYLON.MeshBuilder.CreatePlane(
        'p',
        {
            height:10,
            width:10,
            sideOrientation:BABYLON.Mesh.DOUBLESIDE,
            frontUVS:f,
            backUVs:b
        },
        scene
    )
    let planeMat=new BABYLON.StandardMaterial('mat',scene)
    planeMat.diffuseTexture=new BABYLON.Texture('../img/test.jpg',scene)
    plane.material=planeMat
           
Babylon.js 第21章 材质映射到网格+贴花

三、对不同网格使用多材料

let mat0=new BABYLON.StandardMaterial('mat0',scene)
    mat0.diffuseColor=new BABYLON.Color3(1,0,1)
    mat0.bumpTexture=new BABYLON.Texture('../img/4.png',scene)
    let mat1=new BABYLON.StandardMaterial('mat1',scene)
    mat1.diffuseColor=new BABYLON.Color3(0,0,1)
    let mat2=new BABYLON.StandardMaterial('mat2',scene)
    mat2.emissiveColor=new BABYLON.Color3(1,0,0)

    let multimat=new BABYLON.MultiMaterial('mutl',scene)
    multimat.subMaterials.push(mat0)
    multimat.subMaterials.push(mat1)
    multimat.subMaterials.push(mat2)
    sphere.material=multimat
    sphere.subMeshes=[]
    //获取定点数
    let verticesCount=sphere.getTotalVertices()
    new BABYLON.SubMesh(0,0,verticesCount,0,3000,sphere)
    new BABYLON.SubMesh(1,0,verticesCount,3000,6000,sphere)
    new BABYLON.SubMesh(2,0,verticesCount,6000,7870,sphere)
           

在这种情况下,您将有 3 个部分:

  • 一个从索引 0 开始到索引 900
  • 一个从索引 900 到索引 1800
  • 一个从索引 1800 开始到索引 3880

子网格定义为:

  • 要使用的材质的索引(该索引用于在多材质的subMaterials集合中找到正确的材质)
  • 第一个顶点的索引和使用的顶点数(例如,为了优化碰撞)
  • 要使用的第一个索引的索引和索引计数
  • 父网格

因此,使用上面的代码,您可以在球体顶部使用第一种材料,在中间部分使用第二种材料,在球体底部使用最后一种材料。

四、合并网格

let mat0=new BABYLON.StandardMaterial('mat0',scene)
    mat0.diffuseColor=new BABYLON.Color3(1,0,1)
    mat0.bumpTexture=new BABYLON.Texture('../img/4.png',scene)
    let mat1=new BABYLON.StandardMaterial('mat1',scene)
    mat1.diffuseColor=new BABYLON.Color3(0,0,1)
    let mat2=new BABYLON.StandardMaterial('mat2',scene)
    mat2.emissiveColor=new BABYLON.Color3(1,0,0)
    sphere.material=mat2
    let box=new BABYLON.MeshBuilder.CreateBox('box',
        {width:3,height:15,depth:2},scene)
    box.position.z=-2
    
    box.material=mat1
    let mesh=BABYLON.Mesh.MergeMeshes(
        [sphere,box],
        sphere,
        true,
        undefined,
        false,
        true
        /*
        *将最终参数multiMultiMaterial设置为 true 时,
        *将自动创建包含所有合并网格的子网格的子网格数组。
        *每个 subMesh 的材质也包含在生成的网格的新 multiMaterial 中。
        */
        )
           

 将最后一个参数multiMultiMaterial设置为 true 时,将自动创建包含所有合并网格的子网格的子网格数组。每个 subMesh 的材质也包含在生成的网格的新 multiMaterial 中。此功能忽略参数 ( 

subdivideWithSubMeshes

)。

将倒数第二个参数 ( 

subdivideWithSubMeshes

) 设置为 true,但最后一个参数 ( 

multiMultiMaterial

) 保留为 false 时,将自动创建 subMeshes 数组,其中每个合并网格都作为新网格的子网格。您必须将正确的子网格索引分配给正确的材料索引。

mergedMesh

通过按此数组顺序 [mesh1, mesh2] 合并网格来形成时,multiMaterials subMaterials 数组包含顺序为 [mat1, mat2] 的材料,那么对于 subMesh from

mesh2

具有

mat2

您需要设置的材料

Babylon.js 第21章 材质映射到网格+贴花

四、网格贴花

这些通常用于在网格上添加细节(子弹孔、局部细节等),贴花是从前一个网格的子集生成的网格,具有小的偏移量,以便出现在其顶部。

var decal = BABYLON.MeshBuilder.CreateDecal("decal", mesh,
    {position: myPos}, scene);
           
属性 默认值
position (Vector3)贴花的位置(世界坐标) (0, 0, 0)
normal (Vector3) 贴花应用到的网格的法线(世界坐标) Vector3.Up
size (Vector3) 贴花的 x、y、z 尺寸 (1, 1, 1)
angle (数字)旋转贴花的角度

 贴花示例:

let mat=new BABYLON.StandardMaterial('mat',scene)
    mat.diffuseTexture=new BABYLON.Texture('../img/太阳.png',scene)
    mat.diffuseTexture.hasAlpha=true
    mat.zOffset=-2
    
    let onPointerDown=evt=>{
        if(evt.button!==0){
            return
        }
        let pickInfo=scene.pick(scene.pointerX,
            scene.pointerY,mesh=>{return mesh===ground})
        if(pickInfo.hit){
            let decalSize=new BABYLON.Vector3(1,1,1)
            let opt={
                position:pickInfo.pickedPoint,
                normal:pickInfo.getNormal(true),
                size:decalSize
            }
            let decal=BABYLON.MeshBuilder.CreateDecal('decal',ground,opt,scene)
            decal.material=mat
        }
        
    }
    let canva=engine.getRenderingCanvas()
    canva.addEventListener('p',onPointerDown,false)
    scene.onDispose=()=>{
        canva.removeEventListener('p',onPointerDown)
    }
    canvas.addEventListener("pointerdown", onPointerDown, false);
    scene.onDispose = function () {
        canvas.removeEventListener("pointerdown", onPointerDown);
    }
           
Babylon.js 第21章 材质映射到网格+贴花

继续阅读