Unity中动态创建Mesh (1)

本文详细介绍了Unity3D中Mesh的概念及其重要性,解释了如何使用MeshFilter和MeshRenderer组件创建和渲染3D模型。通过设置顶点、三角形、法线和纹理坐标,可以构建并显示自定义的3D网格。同时,强调了Unity3D仅支持三边面以及法线在渲染中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

引言

3D世界中任何的面都是由三角形绘制完成的,因为任何无规则的集合图形都可以由三角形来组成。比如四边形,无论是正四边形还是无规则四边形都可以由两个三角形拼接而成。如下图,模型上的一个个小网格就是Mesh,这些Mesh有不同的三维顶点(Vector3),共同组成了一个3D模型。

模型网格由一个个三角形组成

什么是Mesh?

Mesh是指的模型的网格,3D模型是由多边形拼接而成,而多边形实际上又是由多个三角形拼接而成的。即一个3D模型的表面其实是由多个彼此相连的三角面构成。三维空间中,构成这些三角形的点和边的集合就是Mesh。

原理

即动态创建一个Mesh,设置三角形和顶点数据,然后赋值给MeshFilter(增加mesh属性),通过MeshRenderer(增加材质并渲染出Mesh)绘制出来。

解析

1.Mesh、MeshFilter、MeshRenderer关系整理

在Unity3D中创建一个Cube,在Inspector可以看到其中含有MeshFilter、MeshRenderer组件。

MeshFilter含有一个Public成员 Mesh。

在Mesh中存储着三维模型的数据:vertices(顶点数据数组Vector3[])、triangles(三角形顶点索引数组,int[])、normals(法线向量数组,Vector3[])、uv(纹理坐标数组,Vector2[])。

2.Unity3D中Mesh的基本单位是三角形,故而从最基本最简单的等腰三角形开始画起。

Mesh是Unity内的一个组件,称为网格组件。

Mesh 网格
MeshFilter 网格过滤器
Mesh Renderer 网格渲染器
Mesh:是指模型的网格,建模就是建网格。细看Mesh,可以知道Mesh的主要属性内容包括顶点坐标,法线,纹理坐标,三角形绘制序列等其他有用属性和功能。因此建网格,就是画三角形;画三角形就是定位三个点。

Mesh Filter:内包含一个Mesh组件,可以根据MeshFilter获得模型网格的组件,也可以为MeshFilter设置Mesh内容。

Mesh Render:是用于把网格渲染出来的组件。MeshFilter的作用就是把Mesh扔给MeshRender将模型或者说是几何体绘制显示出来。

它们之间的关系大概就是Unity中的对象就是GameObject,每个GameObject都可以有一个MeshFilter组件(也可以没有),该组件又有Mesh属性(这个一定有),而该属性又有顶点坐标,法线等属性。而如果GameObject里有MeshFilter,则必须要Mesh Renderer才能将此网格渲染出来,不然是看不见该网格的。

3.Mesh的组成部分
1.vertices(顶点数据数组Vector3[])

2.triangles(三角形顶点索引数组,int[])

3.normals(法线向量数组,Vector3[])

4.uv(纹理坐标数组,Vector2[])

顶点坐标:顶点坐标数组存放Mesh的每个顶点的空间坐标,假设某mesh有n个顶点,则vertex的size为n

法线:法线数组存放mesh每个顶点的法线,大小与顶点坐标对应,normal[i]对应顶点vertex[i]的法线

  法线详解:

     法线就是垂直于面的一条线,它有方向,没有大小。

     法线的方向就是面朝外的方向。比如我们现在盯着显示器看,从显示器的正中心会有一条法线垂直于屏幕指向我们。

     法线向外的面就是正面,相反的就是背面,一般来讲,从正面看才能看到面,背面看面是看不到的。

纹理坐标:它定义了图片上每个点的位置的信息. 这些点与3D模型是相互联系的, 以决定表面纹理贴图的位置. UV就是将图像上每一个点精确对应到模型物体的表面. uv[i]对应vertex[i]

三角形序列:每个mesh都由多个三角面组成,而三角面的三个点就是顶点坐标里的点,三角形的数组的size = 三角形个数 * 3

  三边面和四边面:

    三边面就是三条边组成的面,四边面就是四条边组成的面。

    三边面在三维空间中是不可扭曲的,而四边面在三维空间中可以扭曲。所以Unity里只支持三边面。其他支持四边面的软件例如3dmax在导出fbx的时候,会把四边面转换成三边面。

例如:某mesh有四个顶点0,1,2,3,

V0(1, 1, 0),
V1(-1, 1, 0),
V2(1, -1, 0),
V3(-1, -1, 0)

那么它们可以组成这样的一个网格,

tri[0] = ver[0],ver[3],ver[1],tri[1] = ver[0],ver[2],ver[3];
三角形顶点索引

注意:三角形的顶点顺序必须是顺时针,顺时针表示正面,逆时针表示背面,而unity3d在渲染时默认只渲染正面,背面是看不见的。

那么该三角形可以表示为:

tri = new int[2 * 3]{0, 3, 1, 0, 2, 3};

如何要获取第N个三角形对应的三个顶点坐标,则:v1 = tri[N3 + 0], v2 = tri[N3 + 1], v3 = tir[N*3 + 2]

案例

1.创建一个GameObject并添加MeshFilter以及MeshRender组件,并创建一个“CreateMesh.cs”脚本给它。

2.获取该对象的filter组件,并创建一个mesh给它。

3.为该mesh设置属性,这里先设置顶点,然后将三角形与顶点绑定

using UnityEngine;
using System.Collections;
 
public class CreateMesh : MonoBehaviour {
 
    private MeshFilter filter;
    private Mesh mesh;
 
    // Use this for initialization
    void Start () {
        // 获取GameObject的Filter组件
        filter = GetComponent<MeshFilter>();
        // 并新建一个mesh给它
        mesh = new Mesh();
        filter.mesh = mesh;
 
        // 初始化网格
        InitMesh();
    }
     
    // Update is called once per frame
    void Update () {
     
    }
 
    /// <summary>
    /// Inits the mesh.
    /// </summary>
    void InitMesh()
    {
        mesh.name = "MyMesh";
 
        // 为网格创建顶点数组
        Vector3[] vertices = new Vector3[4]{
            new Vector3(1, 1, 0),
            new Vector3(-1, 1, 0),
            new Vector3(1, -1, 0),
            new Vector3(-1, -1, 0)
        };
 
        mesh.vertices = vertices;
 
        // 通过顶点为网格创建三角形
        int[] triangles = new int[2 * 3]{
            0, 3, 1,   0, 2, 3
        };
 
        mesh.triangles = triangles;
    }
}

效果如图:
网格
3.网格已经成功生成,接下来该给网格贴图了,在Inspector视图里选中Mesh Render,并拖一个材质给它,

Mesh Render是负责渲染的,将Mesh Filter里的mesh通过自身的Materials渲染出来。

设置完材质后,我们需要将纹理贴图与网格顶点一一对应起来,这样才能渲染出来。

// 为mesh设置纹理贴图坐标
        Vector2[] uv = new Vector2[4]{
            new Vector2(1, 1),
            new Vector2(0, 1),
            new Vector2(1, 0),
            new Vector2(0, 0)
        };

        mesh.uv = uv;

效果如图:

渲染效果图

Unity3D动态创建Mesh是一种常见的图形编程任务,尤其适用于需要实时生成或修改几何体的场景。通过C#脚本,开发者可以完全控制Mesh的顶点、三角形索引、法线、纹理坐标等属性[^3]。 ### 动态创建Mesh的基本步骤 1. **创建Mesh对象** 使用`new Mesh()`创建一个新的网格实例,并将其分配给一个`MeshFilter`组件。 2. **定义顶点数组** 顶点是构成网格的基本元素。每个顶点通常包含位置、法线、纹理坐标等信息。 3. **定义三角形索引数组** Unity使用三角形来绘制网格,因此必须将顶点连接成三角形。三角形由三个顶点索引组成。 4. **设置Mesh数据** 使用`mesh.vertices`、`mesh.triangles`等属性将顶点和三角形数据写入Mesh对象。 5. **更新Mesh并应用材质** 最后将Mesh赋值给`MeshFilter`,并为`MeshRenderer`设置合适的材质以进行渲染。 --- ### 示例:动态创建一个正方形平面网格 以下是一个简单的C#脚本示例,展示如何在运行时动态创建一个正方形平面网格: ```csharp using UnityEngine; [RequireComponent(typeof(MeshFilter), typeof(MeshRenderer))] public class DynamicPlaneMesh : MonoBehaviour { public float width = 10f; public float height = 10f; public int xSegments = 10; public int ySegments = 10; void Start() { GenerateMesh(); } void GenerateMesh() { Mesh mesh = new Mesh(); GetComponent<MeshFilter>().mesh = mesh; // 计算顶点数量和三角形数量 int numVerticesX = xSegments + 1; int numVerticesY = ySegments + 1; Vector3[] vertices = new Vector3[numVerticesX * numVerticesY]; Vector2[] uv = new Vector2[vertices.Length]; // 填充顶点和UV坐标 for (int y = 0; y <= ySegments; y++) { for (int x = 0; x <= xSegments; x++) { int index = y * numVerticesX + x; float u = x / (float)xSegments; float v = y / (float)ySegments; vertices[index] = new Vector3(-width * 0.5f + width * u, 0, -height * 0.5f + height * v); uv[index] = new Vector2(u, v); } } // 定义三角形索引 int[] triangles = new int[xSegments * ySegments * 6]; int triIndex = 0; for (int y = 0; y < ySegments; y++) { for (int x = 0; x < xSegments; x++) { int topLeft = y * numVerticesX + x; int topRight = topLeft + 1; int bottomLeft = (y + 1) * numVerticesX + x; int bottomRight = bottomLeft + 1; triangles[triIndex++] = topLeft; triangles[triIndex++] = bottomLeft; triangles[triIndex++] = topRight; triangles[triIndex++] = topRight; triangles[triIndex++] = bottomLeft; triangles[triIndex++] = bottomRight; } } // 应用顶点和三角形数据到Mesh mesh.vertices = vertices; mesh.uv = uv; mesh.triangles = triangles; // 可选:计算法线以获得正确的光照效果 mesh.RecalculateNormals(); } } ``` --- ### 扩展与优化 - **性能优化**:对于复杂的Mesh,应避免频繁调用`RecalculateNormals()`和`RecalculateTangents()`,可以在初始化时一次性计算好。 - **动态更新**:如果希望每帧更新Mesh(如水面波动、地形变形),可将生成逻辑放入`Update()`函数中,并确保只在必要时重新提交顶点数据。 - **其他形状**:通过修改顶点生成逻辑,可以创建圆形、球体、圆柱体等复杂几何体[^2]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天宇琪云

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值