kingBook

导航

Unity Mesh(网格)

Mesh:
  • vertices:
  • normals:
  • uv:
  • tangents:
  • boneWeights :
  • colors/colors32:
//顶点位置数组
public Vector3[] vertices ;

//两种方法更改
//public void SetVertices (List<Vector3> inVertices);
mesh.SetVertices(vertices);
mesh.vertices = vertices;

//改变 vertices 后通常需要重新计算包围盒
mesh.RecalculateBounds();

//每一个顶点的法线方向
public Vector3[] normals ;

//uv列表
public Vector2[] uv ;

//网格的切线。
//切线最常用于凹凸贴图着色器中。切线是单位长度的矢量,它顺着网格 表面沿水平 (U) 纹理方向。Unity 中的切线表示为 Vector4, 其“x,y,z”分量定义矢量,而 w 用于在需要时翻转副法线。
//Unity 计算另一个表面矢量(副法线)的方法是获取法线与切线 之间的叉积,然后将结果乘以切线的 w。因此,w 应始终为 1 或 -1。
//如果计划在网格上使用凹凸贴图着色器,则应自己计算切线。 在分配 normals 或使用 RecalculateNormals 之后分配切线。
//注意:若要对 tangents 进行更改,从 Mesh 复制 切线十分重要。复制和更改 tangents 之后,normals 即可重新分配回 Mesh。
public Vector4[] tangents ;

//每个顶点的骨骼权重。
public BoneWeight[] boneWeights ;

//网格的顶点颜色。
//如果没有顶点颜色可用,则返回空数组。
public Color[] colors ;
//与 colors 相同,但是使用 Color32 结构的性能更好。
public Color32[] colors32 ;
  • triangles:
//该数组是三角形的列表,包含顶点数组的索引,长度必须始终是 3 的倍数。
//使用此属性分配三角形数组时,subMeshCount 设置为 1。如果要具有多个子网格,请使用 SetTriangles。
public int[] triangles ;

public void SetTriangles (int[] triangles, int submesh, bool calculateBounds= true, int baseVertex= 0);
public void SetTriangles (int[] triangles, int submesh);
public void SetTriangles (List<int> triangles, int submesh, bool calculateBounds= true, int baseVertex= 0);
public void SetTriangles (List<int> triangles, int submesh);

public int[] GetTriangles (int submesh);
public int[] GetTriangles (int submesh, bool applyBaseVertex= true);
public void GetTriangles (List<int> triangles, int submesh, bool applyBaseVertex= true);
public void GetTriangles (List<int> triangles, int submesh);

//决定索引的布局为三角形、四边形等
public MeshTopology GetTopology (int submesh);

//* SetIndices 、GetIndices 、GetIndexStart 、GetIndexCount
//* 子网格的 GetIndices 方法得到索引列表,始终是在 mesh.vertices 中截取的范围,范围的起始索引为 GetIndexStart ,数量为 GetIndexCount。
//* 只能通过 SetIndices 来指定截取的范围。
//* 当为 MeshTopology(网格拓扑) 为 MeshTopology.Triangles(三角形) 时, GetIndices 与 GetTriangles 得到的结果是一致的
public void SetIndices (int[] indices, MeshTopology topology, int submesh, bool calculateBounds);
public void SetIndices (int[] indices, MeshTopology topology, int submesh);
public void SetIndices (int[] indices, MeshTopology topology, int submesh, bool calculateBounds= true, int baseVertex= 0);

public void GetIndices (List<int> indices, int submesh);
public int[] GetIndices (int submesh)

public uint GetIndexStart (int submesh);
public uint GetIndexCount (int submesh);

1.从头开始构建网格: 应始终按以下顺序进行: 分配 vertices -> 分配 triangles。

using UnityEngine;

public class Example : MonoBehaviour
{
    Vector3[] newVertices;
    Vector2[] newUV;
    int[] newTriangles;

    void Start()
    {
        Mesh mesh = new Mesh();
        GetComponent<MeshFilter>().mesh = mesh;
        mesh.vertices = newVertices;
        mesh.uv = newUV;
        mesh.triangles = newTriangles;
    }
}

2.每一帧都修改顶点属性:
a) 获取顶点
b) 修改它们
c) 将它们分配回网格。

using UnityEngine;

public class Example : MonoBehaviour
{
    void Update()
    {
        Mesh mesh = GetComponent<MeshFilter>().mesh;
        Vector3[] vertices = mesh.vertices;
        Vector3[] normals = mesh.normals;

        for (var i = 0; i < vertices.Length; i++)
        {
            vertices[i] += normals[i] * Mathf.Sin(Time.time);
        }

        mesh.vertices = vertices;
    }
}

3.连续更改网格三角形和顶点:
a) 调用 Clear 以开始刷新
b) 分配顶点和其他属性
c) 分配三角形索引。
在分配新顶点或三角形之前调用 Clear 十分重要。 Unity 始终检查提供的三角形索引是否未引用超出边界的顶点。 调用 Clear,分配顶点,然后分配三角形可确保不会有超出边界的数据。

using UnityEngine;

public class ExampleClass : MonoBehaviour
{
    Vector3[] newVertices;
    Vector2[] newUV;
    int[] newTriangles;

    void Start()
    {
        Mesh mesh = GetComponent<MeshFilter>().mesh;

        mesh.Clear();

        // Do some calculations...
        mesh.vertices = newVertices;
        mesh.uv = newUV;
        mesh.triangles = newTriangles;
    }
}
创建四边形示例

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

public class TestCreateMesh : MonoBehaviour{
	public float width=2f;
	public float height=1f;
	private void Start(){
		MeshFilter mf = GetComponent<MeshFilter>();
		Mesh mesh = new Mesh();
		mf.mesh = mesh;
	
		Vector3[] vertices = new Vector3[4];
		vertices[0] = new Vector3(0, 0, 0);
		vertices[1] = new Vector3(width, 0, 0);
		vertices[2] = new Vector3(0, height, 0);
		vertices[3] = new Vector3(width, height, 0);
		mesh.vertices = vertices;
	

		int[] tri = new int[6];
		tri[0] = 0;
		tri[1] = 2;
		tri[2] = 1;
	
		tri[3] = 2;
		tri[4] = 3;
		tri[5] = 1;
		mesh.triangles = tri;
	
		Vector3[] normals = new Vector3[4];
		normals[0] = Vector3.back;
		normals[1] = Vector3.back;
		normals[2] = Vector3.back;
		normals[3] = Vector3.back;
		mesh.normals = normals;
	
		Vector2[] uv = new Vector2[4];
		uv[0] = new Vector2(0, 0);
		uv[1] = new Vector2(1, 0);
		uv[2] = new Vector2(0, 1);
		uv[3] = new Vector2(1, 1);
		mesh.uv = uv;
	}

}
不同材质多个子网格示例(在上面例子基础上,在左侧添加一个不同材质的矩形)
using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TestCreateMesh : MonoBehaviour{
	public float width=2f;
	public float height=1f;
	private void Start(){
		MeshFilter mf = GetComponent<MeshFilter>();
		Mesh mesh = new Mesh();
		mf.mesh = mesh;
	
		Vector3[] vertices = new Vector3[4];
		vertices[0] = new Vector3(0, 0, 0);
		vertices[1] = new Vector3(width, 0, 0);
		vertices[2] = new Vector3(0, height, 0);
		vertices[3] = new Vector3(width, height, 0);
		mesh.vertices = vertices;

		int[] tri = new int[6];
		tri[0] = 0;
		tri[1] = 2;
		tri[2] = 1;
	
		tri[3] = 2;
		tri[4] = 3;
		tri[5] = 1;
		mesh.triangles = tri;
	
		Vector3[] normals = new Vector3[4];
		normals[0] = Vector3.back;
		normals[1] = Vector3.back;
		normals[2] = Vector3.back;
		normals[3] = Vector3.back;
		mesh.normals = normals;
	
		Vector2[] uv = new Vector2[4];
		uv[0] = new Vector2(0, 0);
		uv[1] = new Vector2(1, 0);
		uv[2] = new Vector2(0, 1);
		uv[3] = new Vector2(1, 1);
		mesh.uv = uv;



		//********************************
		//在左侧添加一个不同材质的矩形。注意: MeshRenderer.Materials 需要设置2个材质
		Vector3[] vertices2=new Vector3[vertices.Length+4];
		Array.Copy(vertices,vertices2,4);
		vertices2[4] = new Vector3(0, 0, width);
		vertices2[5] = new Vector3(0, 0, 0);
		vertices2[6] = new Vector3(0, height, width);
		vertices2[7] = new Vector3(0, height, 0);
		mesh.vertices=vertices2;

		int[] tri2 = new int[tri.Length+6];
		Array.Copy(tri,tri2,6);
		tri2[6] = 4;
		tri2[7] = 6;
		tri2[8] = 5;
	
		tri2[9] = 6;
		tri2[10] = 7;
		tri2[11] = 5;
		mesh.triangles = tri2;

		Vector3[] normals2 = new Vector3[normals.Length+4];
		Array.Copy(normals,normals2,4);
		normals2[4] = Vector3.left;
		normals2[5] = Vector3.left;
		normals2[6] = Vector3.left;
		normals2[7] = Vector3.left;
		mesh.normals = normals2;
	
		Vector2[] uv2 = new Vector2[uv.Length+4];
		Array.Copy(uv,uv2,4);
		uv2[4] = new Vector2(0, 0);
		uv2[5] = new Vector2(1, 0);
		uv2[6] = new Vector2(0, 1);
		uv2[7] = new Vector2(1, 1);
		mesh.uv = uv2;

		mesh.subMeshCount=2;
		
		//方法1:使用 SetIndices 方法 MeshTopology.Triangles 时,索引列表必须为3的倍数
		mesh.SetIndices(new int[]{0,2,1, 2,3,1},MeshTopology.Triangles,0,true);
		mesh.SetIndices(new int[]{4,6,5, 6,7,5},MeshTopology.Triangles,1,true);
		//方法2:使用 SetTriangles
		//mesh.SetTriangles(new int[]{0,2,1, 2,3,1},0,true);
		//mesh.SetTriangles(new int[]{4,6,5, 6,7,5},1,true);
		
	}

}

程序化网格几何体(Unity)
https://docs.unity.cn/cn/current/Manual/GeneratingMeshGeometryProcedurally.html
Mesh(Unity)
https://docs.unity.cn/cn/current/ScriptReference/Mesh.html

Unity中动态创建Mesh
https://www.cnblogs.com/answer-yj/p/11231247.html
使用Mesh创建一个Cube
https://www.cnblogs.com/kyokuhuang/p/4191169.html
水模型动态运动
https://blog.csdn.net/qwsx789/article/details/80351385

关于图形切割的问题
https://blog.csdn.net/thunderdreamer_or/article/details/104184589
unity实现任意多边形三角剖分
https://blog.csdn.net/huangzengman/article/details/77114082

图片转化为3d物体插件_UCLA Mesh Creator
https://blog.csdn.net/lizhenxiqnmlgb/article/details/82854800

将SpriteRenderer组件转换为Mesh
https://www.weixiuzhan.cn/news/show-17973.html

posted on 2020-08-13 14:50  kingBook  阅读(1339)  评论(0编辑  收藏  举报