Unity模型合并调研(2)_Mesh

底层Mesh合并研究

之前Unity模型合并调研(2)的那些代码都是基于CombineMeshes这个函数的包装,可以说没有任何"核心技术"的,接下来研究一下Mesh的底层。

加深对Mesh的理解。然后去看看MeshBaker,这个插件里面没用用到CombineMeshes是自己修改的Mesh。后面还要去看看ProBuilder。

1.创建Mesh

1.1 Plane

参考:https://blog.csdn.net/qq_22472397/article/details/81263155

照着抄了一下

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlaneCreator : MonoBehaviour
{
    public int width=10;
    public int height=10;
    public Color color=Color.green;
    public GameObject result;
    public const string DefaultShader="HDRP/Lit";//"Standard","HDRP/Lit"

    // Start is called before the first frame update
    void Start()
    {
        result=GenerateGO();
    }

    private Mesh GenerateMesh(){
        Mesh mesh=new Mesh();
        int x=0;
        int y=0;

        //创建顶点和UV
        Vector3[] vertices=new Vector3[height*width];
        Vector2[] uv=new Vector2[height*width];

        //把uv缩放到0-1
        Vector2 uvScale=new Vector2(1.0f/(width-1),1.0f/(height-1));
        for(y=0;y<height;y++)
        {
            for(x=0;x<width;x++)
            {
                vertices[y*width+x]=new Vector3(x,0,y);
                uv[y*width+x]=Vector2.Scale(new Vector2(x,y),uvScale);
            }
        }

        mesh.vertices=vertices;
        mesh.uv=uv;

        //三角形index
        int[] triangles=new int[(height-1)*(width-1)*6];
        int index=0;
        for(y=0;y<height-1;y++)
        {
            for(x=0;x<width-1;x++)
            {
                //每个格子2个三角形,总共6个index
                triangles[index++]=(y*width)+x;
                triangles[index++]=((y+1)*width)+x;
                triangles[index++]=(y*width)+x+1;

                triangles[index++]=((y+1)*width)+x;
                triangles[index++]=((y+1)*width)+x+1;
                triangles[index++]=(y*width)+x+1;
            }
        }
        mesh.triangles=triangles;
        mesh.RecalculateNormals();
        return mesh;
    }

    private GameObject GenerateGO(){
        GameObject obj=new GameObject("Mesh_Plane");
        MeshFilter meshFilter=obj.AddComponent<MeshFilter>();
        //创建mesh
        Mesh mesh=GenerateMesh();
        meshFilter.mesh=mesh;
        MeshRenderer renderer=obj.AddComponent<MeshRenderer>();
        //创建材质
        Material mat=new Material(Shader.Find(DefaultShader));
        //mat.color=Color.green;
        mat.SetColor("_BaseColor",color);
        renderer.material=mat;
        return obj;
    }

    [ContextMenu("Recreate")]
    private void Recreate(){
        if(result)
            GameObject.DestroyImmediate(result);
        result=GenerateGO();
    }
}

1.修改1 width,height

10*10的参数,创建出来的是0-9的Plane。4*4创建出来的是3*3,总觉得怪怪的。

具体算法部分我是不会改的,不过既然都差一,在进入算法前,设置一下就好了。这样就符合直观感受了。

    private Mesh GenerateMesh(){
        int h=height+1;
        int w=width+1;
        //..后面都是h,w了。
    }

2.修改2 密度

加个密度参数,这里的Plane里面两个点之间的距离是1,实际上对于一些模型来说太大了,修改一下它的密度。

public float scale=1;//密度
        Vector2 uvScale=new Vector2(1.0f/(w-1),1.0f/(h-1));
        for(y=0;y<h;y++)
        {
            for(x=0;x<w;x++)
            {
                vertices[y*w+x]=new Vector3(x*scale,0,y*scale);
                uv[y*w+x]=Vector2.Scale(new Vector2(x,y),uvScale);
            }
        }

看起来和5*5是一样的,但是点的数量增加了

3.uv

对于纯色的材质,没有设置uv也没有影响的,但是对于有贴图的材质,没有uv,则没有贴图,和用3dmax建模但是没分uv的模型状态一样。这时候从数据上讲mesh.uv的数组的数据是空的。

对于Plane平面来说uv还好算的,正方体也好算的,但是对于其他模型uv怎么弄呢,立体的三角形,椎体,球体。

对于HDRP/Lit材质来说,Base UI mapping有个Planar和Triplanar的选项,可以给没有uv的模型显示贴图。

对于Plane来说,感觉像是直接把顶点坐标给了uv用。

移动模型,贴图真的是按照世界坐标来的。

4.法线

RecalculateNormals()没使用也是可以的,看不出区别。

RecalculateNormals()官方说明(https://docs.unity3d.com/2017.2/Documentation/ScriptReference/Mesh.RecalculateNormals.html)是根据顶点和三角面计算出来的。

只能说对于Plane来说,默认就是正确的。看了下,RecalculateNormals()后,mesh.normals的数据都是(0,1,0)

本来我考虑把normals都改成(0,-1,0),应该是上面没显示,下面显示,结果不是

变成了

是那种场景中没有光照时的效果,也就是说法线反了后,不影响是否显示,影响了光照量。

学了些shader后现在能理解了,就是光照和法线的夹角问题。

官网有个例子(https://docs.unity3d.com/2017.2/Documentation/ScriptReference/Mesh-normals.html),旋转法线,对于Plane来说,绕着up旋转,怎么转都一样的, 要改一下,dir。

public class RotateNormal : MonoBehaviour
{
    public float speed = 100.0f;

    public Vector3 dir=Vector3.up;

    public MeshFilter meshFilter=null;

    public Quaternion rotation;

    void Start()
    {
        meshFilter=GetComponent<MeshFilter>();
    }

    public Vector3[] normals;

    // Update is called once per frame
    void Update()
    {
        // obtain the normals from the Mesh
        Mesh mesh = meshFilter.mesh;
        //Vector3[] normals = mesh.normals;
        normals = mesh.normals;
        // edit the normals in an external array
        rotation = Quaternion.AngleAxis(Time.deltaTime * speed, dir);

        for (int i = 0; i < normals.Length; i++)
            normals[i] = rotation * normals[i];

        // assign the array of normals to the mesh
        mesh.normals = normals;
    }
}

 

2.修改Mesh

 

3.合并Mesh

4.保存Mesh

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值